+#include
int main(int argc, char *argv[])
{
@@ -52,6 +54,14 @@ int main(int argc, char *argv[])
reporter.setWindowTitle(CRASHREPORTER_PRODUCT_NAME);
reporter.setText("Sorry! " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.
");
+ const QFileInfo crashLog(QDir::tempPath() + QStringLiteral("/" CRASHREPORTER_PRODUCT_NAME "-crash.log"));
+ if (crashLog.exists()) {
+ QFile inFile(crashLog.filePath());
+ if (inFile.open(QFile::ReadOnly)) {
+ reporter.setComment(inFile.readAll());
+ }
+ }
+
reporter.setReportData("BuildID", CRASHREPORTER_BUILD_ID);
reporter.setReportData("ProductName", CRASHREPORTER_PRODUCT_NAME);
reporter.setReportData("Version", CRASHREPORTER_VERSION_STRING);
diff --git a/src/csync/CMakeLists.txt b/src/csync/CMakeLists.txt
index 2a7cdff6df7c..ec655df6783d 100644
--- a/src/csync/CMakeLists.txt
+++ b/src/csync/CMakeLists.txt
@@ -58,10 +58,11 @@ endif()
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
-add_library("${csync_NAME}" SHARED ${common_SOURCES} ${csync_SRCS})
+add_library(nextcloud_csync SHARED ${common_SOURCES} ${csync_SRCS})
+add_library(Nextcloud::csync ALIAS nextcloud_csync)
target_include_directories(
- "${csync_NAME}"
+ nextcloud_csync
PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/std
)
@@ -69,26 +70,26 @@ if(USE_OUR_OWN_SQLITE3)
message(STATUS "Using own sqlite3 version")
add_library(sqlite3 STATIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3/sqlite3.c")
target_include_directories(sqlite3 PUBLIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3")
- target_link_libraries("${csync_NAME}" PUBLIC sqlite3)
+ target_link_libraries(nextcloud_csync PUBLIC sqlite3)
else()
- target_include_directories("${csync_NAME}" PUBLIC ${SQLITE3_INCLUDE_DIR})
- target_link_libraries("${csync_NAME}" PUBLIC ${SQLITE3_LIBRARIES})
+ target_include_directories(nextcloud_csync PUBLIC ${SQLITE3_INCLUDE_DIR})
+ target_link_libraries(nextcloud_csync PUBLIC ${SQLITE3_LIBRARIES})
endif()
-generate_export_header("${csync_NAME}"
+generate_export_header(nextcloud_csync
EXPORT_MACRO_NAME OCSYNC_EXPORT
EXPORT_FILE_NAME ocsynclib.h
)
-target_link_libraries("${csync_NAME}"
+target_link_libraries(nextcloud_csync
PUBLIC
${CSYNC_REQUIRED_LIBRARIES}
Qt5::Core Qt5::Concurrent
)
if(ZLIB_FOUND)
- target_link_libraries("${csync_NAME}" PUBLIC ZLIB::ZLIB)
+ target_link_libraries(nextcloud_csync PUBLIC ZLIB::ZLIB)
endif(ZLIB_FOUND)
@@ -96,11 +97,11 @@ endif(ZLIB_FOUND)
if (APPLE)
find_library(FOUNDATION_LIBRARY NAMES Foundation)
find_library(CORESERVICES_LIBRARY NAMES CoreServices)
- target_link_libraries("${csync_NAME}" PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
+ target_link_libraries(nextcloud_csync PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
endif()
set_target_properties(
- "${csync_NAME}"
+ nextcloud_csync
PROPERTIES
VERSION
${LIBRARY_VERSION}
@@ -108,11 +109,15 @@ set_target_properties(
${LIBRARY_SOVERSION}
RUNTIME_OUTPUT_DIRECTORY
${BIN_OUTPUT_DIRECTORY}
+ LIBRARY_OUTPUT_NAME
+ ${APPLICATION_EXECUTABLE}_csync
+ RUNTIME_OUTPUT_NAME
+ ${APPLICATION_EXECUTABLE}_csync
)
if(BUILD_OWNCLOUD_OSX_BUNDLE)
INSTALL(
TARGETS
- "${csync_NAME}"
+ nextcloud_csync
LIBRARY DESTINATION
${LIB_INSTALL_DIR}
ARCHIVE DESTINATION
@@ -123,7 +128,7 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE)
else()
INSTALL(
TARGETS
- "${csync_NAME}"
+ nextcloud_csync
LIBRARY DESTINATION
${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION
diff --git a/src/csync/ConfigureChecks.cmake b/src/csync/ConfigureChecks.cmake
index 9aac6673ac14..64bdf1770ee6 100644
--- a/src/csync/ConfigureChecks.cmake
+++ b/src/csync/ConfigureChecks.cmake
@@ -7,7 +7,6 @@ include(CheckCXXSourceCompiles)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
-set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
@@ -23,6 +22,12 @@ if (NOT LINUX)
check_library_exists(rt nanosleep "" HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
+
+ # Systems not using glibc require linker flag for argp
+ check_library_exists(argp argp_parse "" HAVE_LIBARGP)
+ if(HAVE_ARGP_H AND HAVE_LIBARGP)
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} argp)
+ endif()
endif (NOT LINUX)
if(WIN32)
diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp
index f9968ae7b89e..eb850758917a 100644
--- a/src/csync/csync_exclude.cpp
+++ b/src/csync/csync_exclude.cpp
@@ -19,6 +19,7 @@
*/
#include "config_csync.h"
+#include
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -34,10 +35,8 @@
#include
#include
-#include
#include
-
/** Expands C-like escape sequences (in place)
*/
OCSYNC_EXPORT void csync_exclude_expand_escapes(QByteArray &input)
@@ -199,13 +198,13 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QString &path, bool exclu
}
#endif
- /* We create a Desktop.ini on Windows for the sidebar icon, make sure we don't sync it. */
- if (blen == 11 && path == bname) {
- if (bname.compare(QLatin1String("Desktop.ini"), Qt::CaseInsensitive) == 0) {
- return CSYNC_FILE_SILENTLY_EXCLUDED;
- }
+ /* Do not sync desktop.ini files anywhere in the tree. */
+ const auto desktopIniFile = QStringLiteral("desktop.ini");
+ if (blen == static_cast(desktopIniFile.length()) && bname.compare(desktopIniFile, Qt::CaseInsensitive) == 0) {
+ return CSYNC_FILE_SILENTLY_EXCLUDED;
}
+
if (excludeConflictFiles && OCC::Utility::isConflictFile(path)) {
return CSYNC_FILE_EXCLUDE_CONFLICT;
}
@@ -231,24 +230,21 @@ ExcludedFiles::ExcludedFiles(const QString &localPath)
// We're in a detached exclude probably coming from a partial sync or test
if (_localPath.isEmpty())
return;
-
- // Load exclude file from base dir
- QFileInfo fi(_localPath + QStringLiteral(".sync-exclude.lst"));
- if (fi.isReadable())
- addInTreeExcludeFilePath(fi.absoluteFilePath());
}
ExcludedFiles::~ExcludedFiles() = default;
void ExcludedFiles::addExcludeFilePath(const QString &path)
{
- _excludeFiles[_localPath].append(path);
-}
-
-void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
-{
- BasePathString basePath = leftIncludeLast(path, QLatin1Char('/'));
- _excludeFiles[basePath].append(path);
+ const QFileInfo excludeFileInfo(path);
+ const auto fileName = excludeFileInfo.fileName();
+ const auto basePath = fileName.compare(QStringLiteral("sync-exclude.lst"), Qt::CaseInsensitive) == 0
+ ? _localPath
+ : leftIncludeLast(path, QLatin1Char('/'));
+ auto &excludeFilesLocalPath = _excludeFiles[basePath];
+ if (std::find(excludeFilesLocalPath.cbegin(), excludeFilesLocalPath.cend(), path) == excludeFilesLocalPath.cend()) {
+ excludeFilesLocalPath.append(path);
+ }
}
void ExcludedFiles::setExcludeConflictFiles(bool onoff)
@@ -288,32 +284,26 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
_clientVersion = version;
}
-bool ExcludedFiles::loadExcludeFile(const QString &basePath, const QString & file)
+void ExcludedFiles::loadExcludeFilePatterns(const QString &basePath, QFile &file)
{
- QFile f(file);
- if (!f.open(QIODevice::ReadOnly))
- return false;
-
QStringList patterns;
- while (!f.atEnd()) {
- QByteArray line = f.readLine().trimmed();
+ while (!file.atEnd()) {
+ QByteArray line = file.readLine().trimmed();
if (line.startsWith("#!version")) {
if (!versionDirectiveKeepNextLine(line))
- f.readLine();
+ file.readLine();
}
if (line.isEmpty() || line.startsWith('#'))
continue;
csync_exclude_expand_escapes(line);
patterns.append(QString::fromUtf8(line));
}
- _allExcludes.insert(basePath, patterns);
+ _allExcludes[basePath].append(patterns);
// nothing to prepare if the user decided to not exclude anything
if (!_allExcludes.value(basePath).isEmpty()){
prepare(basePath);
}
-
- return true;
}
bool ExcludedFiles::reloadExcludeFiles()
@@ -330,8 +320,14 @@ bool ExcludedFiles::reloadExcludeFiles()
bool success = true;
const auto keys = _excludeFiles.keys();
for (const auto& basePath : keys) {
- for (const auto& file : _excludeFiles.value(basePath)) {
- success = loadExcludeFile(basePath, file);
+ for (const auto &excludeFile : _excludeFiles.value(basePath)) {
+ QFile file(excludeFile);
+ if (file.exists() && file.open(QIODevice::ReadOnly)) {
+ loadExcludeFilePatterns(basePath, file);
+ } else {
+ success = false;
+ qWarning() << "System exclude list file could not be opened:" << excludeFile;
+ }
}
}
@@ -422,11 +418,14 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
// Directories are guaranteed to be visited before their files
if (filetype == ItemTypeDirectory) {
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
- const auto fi = QFileInfo(basePath + QStringLiteral(".sync-exclude.lst"));
+ const QString absolutePath = basePath + QStringLiteral(".sync-exclude.lst");
+ QFileInfo excludeFileInfo(absolutePath);
- if (fi.isReadable()) {
- addInTreeExcludeFilePath(fi.absoluteFilePath());
- loadExcludeFile(basePath, fi.absoluteFilePath());
+ if (excludeFileInfo.isReadable()) {
+ addExcludeFilePath(absolutePath);
+ reloadExcludeFiles();
+ } else {
+ qWarning() << "System exclude list file could not be read:" << absolutePath;
}
}
diff --git a/src/csync/csync_exclude.h b/src/csync/csync_exclude.h
index bbb0a2cda965..856ac67eff8a 100644
--- a/src/csync/csync_exclude.h
+++ b/src/csync/csync_exclude.h
@@ -48,6 +48,7 @@ enum CSYNC_EXCLUDE_TYPE {
};
class ExcludedFilesTest;
+class QFile;
/**
* Manages file/directory exclusion.
@@ -69,7 +70,7 @@ class OCSYNC_EXPORT ExcludedFiles : public QObject
using Version = std::tuple;
explicit ExcludedFiles(const QString &localPath = QStringLiteral("/"));
- ~ExcludedFiles();
+ ~ExcludedFiles() override;
/**
* Adds a new path to a file containing exclude patterns.
@@ -77,7 +78,6 @@ class OCSYNC_EXPORT ExcludedFiles : public QObject
* Does not load the file. Use reloadExcludeFiles() afterwards.
*/
void addExcludeFilePath(const QString &path);
- void addInTreeExcludeFilePath(const QString &path);
/**
* Whether conflict files shall be excluded.
@@ -148,7 +148,7 @@ public slots:
/**
* Loads the exclude patterns from file the registered base paths.
*/
- bool loadExcludeFile(const QString &basePath, const QString &file);
+ void loadExcludeFilePatterns(const QString &basePath, QFile &file);
private:
/**
diff --git a/src/csync/vio/csync_vio_local_win.cpp b/src/csync/vio/csync_vio_local_win.cpp
index 7aa07f4da4ea..4ddd4f545fa4 100644
--- a/src/csync/vio/csync_vio_local_win.cpp
+++ b/src/csync/vio/csync_vio_local_win.cpp
@@ -34,6 +34,7 @@
#include "csync.h"
#include "vio/csync_vio_local.h"
#include "common/filesystembase.h"
+#include "common/utility.h"
#include
@@ -52,8 +53,6 @@ struct csync_vio_handle_t {
QString path; // Always ends with '\'
};
-static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf);
-
csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
QScopedPointer handle(new csync_vio_handle_t{});
@@ -175,12 +174,9 @@ std::unique_ptr csync_vio_local_readdir(csync_vio_handle_t *h
file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
- QString fullPath;
- fullPath.reserve(handle->path.size() + std::wcslen(handle->ffd.cFileName));
- fullPath += handle->path; // path always ends with '\', by construction
- fullPath += QString::fromWCharArray(handle->ffd.cFileName);
+ // path always ends with '\', by construction
- if (_csync_vio_local_stat_mb(fullPath, file_stat.get()) < 0) {
+ if (csync_vio_local_stat(handle->path + QString::fromWCharArray(handle->ffd.cFileName), file_stat.get()) < 0) {
// Will get excluded by _csync_detect_update.
file_stat->type = ItemTypeSkip;
}
@@ -188,14 +184,7 @@ std::unique_ptr csync_vio_local_readdir(csync_vio_handle_t *h
return file_stat;
}
-
int csync_vio_local_stat(const QString &uri, csync_file_stat_t *buf)
-{
- int rc = _csync_vio_local_stat_mb(uri, buf);
- return rc;
-}
-
-static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
{
/* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
But we still need to fetch the file ID.
@@ -206,21 +195,19 @@ static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
BY_HANDLE_FILE_INFORMATION fileInfo;
ULARGE_INTEGER FileIndex;
- const auto longPath = OCC::FileSystem::longWinPath(path);
-
- h = CreateFileW(longPath.toStdWString().data(), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
- nullptr, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
- nullptr );
+ h = CreateFileW(reinterpret_cast(OCC::FileSystem::longWinPath(uri).utf16()), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+ NULL);
if( h == INVALID_HANDLE_VALUE ) {
- qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << longPath;
errno = GetLastError();
+ qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << uri << OCC::Utility::formatWinError(errno);
return -1;
}
if(!GetFileInformationByHandle( h, &fileInfo ) ) {
- qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << longPath;
errno = GetLastError();
+ qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << uri << OCC::Utility::formatWinError(errno);
CloseHandle(h);
return -1;
}
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 6b365afd81a1..a29518fe02ce 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,5 +1,8 @@
project(gui)
-find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2)
+find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 Xml Network)
+if (NOT TARGET Qt5::GuiPrivate)
+ message(FATAL_ERROR "Could not find GuiPrivate component of Qt5. It might be shipped as a separate package, please check that.")
+endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DQT_QML_DEBUG)
@@ -18,6 +21,7 @@ set(theme_dir ${CMAKE_SOURCE_DIR}/theme)
set(client_UI_SRCS
accountsettings.ui
conflictdialog.ui
+ invalidfilenamedialog.ui
foldercreationdialog.ui
folderwizardsourcepage.ui
folderwizardtargetpage.ui
@@ -35,17 +39,27 @@ set(client_UI_SRCS
addcertificatedialog.ui
proxyauthdialog.ui
mnemonicdialog.ui
+ UserStatusSelector.qml
+ UserStatusSelectorDialog.qml
tray/ActivityActionButton.qml
tray/ActivityItem.qml
+ tray/ActivityList.qml
tray/Window.qml
tray/UserLine.qml
+ tray/UnifiedSearchInputContainer.qml
+ tray/UnifiedSearchResultFetchMoreTrigger.qml
+ tray/UnifiedSearchResultItem.qml
+ tray/UnifiedSearchResultItemSkeleton.qml
+ tray/UnifiedSearchResultItemSkeletonContainer.qml
+ tray/UnifiedSearchResultListItem.qml
+ tray/UnifiedSearchResultNothingFound.qml
+ tray/UnifiedSearchResultSectionItem.qml
wizard/flow2authwidget.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudoauthcredspage.ui
wizard/owncloudsetupnocredspage.ui
- wizard/owncloudwizardresultpage.ui
wizard/webview.ui
wizard/welcomepage.ui
)
@@ -54,6 +68,7 @@ set(client_SRCS
accountmanager.cpp
accountsettings.cpp
application.cpp
+ invalidfilenamedialog.cpp
conflictdialog.cpp
conflictsolver.cpp
connectionvalidator.cpp
@@ -86,15 +101,14 @@ set(client_SRCS
sharelinkwidget.cpp
sharemanager.cpp
shareusergroupwidget.cpp
+ profilepagewidget.cpp
sharee.cpp
- socketapi.cpp
sslbutton.cpp
sslerrordialog.cpp
syncrunfilelog.cpp
systray.cpp
thumbnailjob.cpp
userinfo.cpp
- userstatus.cpp
accountstate.cpp
addcertificatedialog.cpp
authenticationdialog.cpp
@@ -105,13 +119,21 @@ set(client_SRCS
guiutility.cpp
elidedlabel.cpp
headerbanner.cpp
- iconjob.cpp
+ iconutils.cpp
remotewipe.cpp
- tray/ActivityData.cpp
- tray/ActivityListModel.cpp
- tray/UserModel.cpp
- tray/NotificationHandler.cpp
- tray/NotificationCache.cpp
+ userstatusselectormodel.cpp
+ emojimodel.cpp
+ fileactivitylistmodel.cpp
+ tray/svgimageprovider.cpp
+ tray/syncstatussummary.cpp
+ tray/activitydata.cpp
+ tray/activitylistmodel.cpp
+ tray/unifiedsearchresult.cpp
+ tray/unifiedsearchresultimageprovider.cpp
+ tray/unifiedsearchresultslistmodel.cpp
+ tray/usermodel.cpp
+ tray/notificationhandler.cpp
+ tray/notificationcache.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
@@ -129,7 +151,6 @@ set(client_SRCS
wizard/owncloudsetuppage.cpp
wizard/owncloudwizardcommon.cpp
wizard/owncloudwizard.cpp
- wizard/owncloudwizardresultpage.cpp
wizard/slideshow.cpp
wizard/welcomepage.cpp
wizard/linklabel.cpp
@@ -241,13 +262,13 @@ if (NOT DEFINED APPLICATION_ICON_NAME)
endif()
# Generate png icons from svg
-find_program(INKSCAPE
- NAMES inkscape inkscape.exe
+find_program(SVG_CONVERTER
+ NAMES inkscape inkscape.exe rsvg-convert
REQUIRED
- HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV INKSCAPE_DIR)
+ HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV SVG_CONVERTER_DIR)
# REQUIRED keyword is only supported on CMake 3.18 and above
-if (NOT INKSCAPE)
- message(FATAL_ERROR "Could not find inkscape. Set INKSCAPE_DIR to the path of executable.")
+if (NOT SVG_CONVERTER)
+ message(FATAL_ERROR "Could not find a suitable svg converter. Set SVG_CONVERTER_DIR to the path of either the inkscape or rsvg-convert executable.")
endif()
function(generate_sized_png_from_svg icon_path size)
@@ -261,16 +282,16 @@ function(generate_sized_png_from_svg icon_path size)
set(icon_output_name "${size}-${icon_name_wle}.png")
message(STATUS "Generate ${icon_output_name}")
execute_process(COMMAND
- "${INKSCAPE}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
+ "${SVG_CONVERTER}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
WORKING_DIRECTORY "${icon_name_dir}"
RESULT_VARIABLE
- INKSCAPE_SIDEBAR_ERROR
+ SVG_CONVERTER_SIDEBAR_ERROR
OUTPUT_QUIET
ERROR_QUIET)
- if (INKSCAPE_SIDEBAR_ERROR)
+ if (SVG_CONVERTER_SIDEBAR_ERROR)
message(FATAL_ERROR
- "inkscape could not generate icon: ${INKSCAPE_SIDEBAR_ERROR}")
+ "${SVG_CONVERTER} could not generate icon: ${SVG_CONVERTER_SIDEBAR_ERROR}")
else()
endif()
endfunction()
@@ -330,6 +351,7 @@ add_library(nextcloudCore STATIC ${final_src})
target_link_libraries(nextcloudCore
PUBLIC
+ Nextcloud::sync
Qt5::Widgets
Qt5::GuiPrivate
Qt5::Svg
@@ -338,9 +360,10 @@ target_link_libraries(nextcloudCore
Qt5::Qml
Qt5::Quick
Qt5::QuickControls2
- ${synclib_NAME}
)
+add_subdirectory(socketapi)
+
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
target_link_libraries(nextcloudCore PUBLIC Qt5::WebEngineWidgets)
endif()
@@ -368,9 +391,9 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
foreach(_file ${_icons})
string(REPLACE "${theme_dir}/colored/" "" _res ${_file})
string(REPLACE "-${APPLICATION_ICON_NAME}-icon.png" "" _res ${_res})
- install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps)
+ install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}x${_res}/apps)
endforeach(_file)
- install(FILES ${client_I18N} DESTINATION ${SHAREDIR}/${APPLICATION_EXECUTABLE}/i18n)
+ install(FILES ${client_I18N} DESTINATION ${CMAKE_INSTALL_DATADIR}/${APPLICATION_EXECUTABLE}/i18n)
else()
file(GLOB_RECURSE VISUAL_ELEMENTS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-w10startmenu*")
install(FILES ${VISUAL_ELEMENTS} DESTINATION bin/visualelements)
@@ -379,17 +402,23 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
endif()
# we may not add MACOSX_BUNDLE here, if not building one
- add_executable(${APPLICATION_EXECUTABLE} WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
+ add_executable(nextcloud WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
+ set_target_properties(nextcloud PROPERTIES
+ OUTPUT_NAME "${APPLICATION_EXECUTABLE}"
+ )
else()
# set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
set(MACOSX_BUNDLE_ICON_FILE "${APPLICATION_ICON_NAME}.icns")
# we must add MACOSX_BUNDLE only if building a bundle
- add_executable(${APPLICATION_EXECUTABLE} WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
+ add_executable(nextcloud WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
if (BUILD_OWNCLOUD_OSX_BUNDLE)
- set_target_properties(${APPLICATION_EXECUTABLE} PROPERTIES
+ set_target_properties(nextcloud PROPERTIES
OUTPUT_NAME "${APPLICATION_NAME}")
+ else()
+ set_target_properties(nextcloud PROPERTIES
+ OUTPUT_NAME "${APPLICATION_EXECUTABLE}")
endif()
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
@@ -409,22 +438,17 @@ endif()
IF(BUILD_UPDATER)
add_library(updater STATIC ${updater_SRCS})
- target_link_libraries(updater ${synclib_NAME} ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
+ target_link_libraries(updater Nextcloud::sync ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(updater PROPERTIES AUTOMOC ON)
+ target_link_libraries(nextcloudCore PUBLIC updater)
endif()
-set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
+set_target_properties(nextcloud PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)
-target_link_libraries(${APPLICATION_EXECUTABLE} nextcloudCore)
-
-IF(BUILD_UPDATER)
- target_link_libraries(nextcloudCore PUBLIC updater)
-endif()
-
-target_link_libraries(nextcloudCore PUBLIC ${OS_SPECIFIC_LINK_LIBRARIES})
+target_link_libraries(nextcloud PRIVATE nextcloudCore)
if(TARGET PkgConfig::CLOUDPROVIDERS)
message("Building with libcloudproviderssupport")
@@ -470,11 +494,7 @@ if(WITH_CRASHREPORTER)
endif()
endif()
-# application.cpp still uses QDesktopServices::storageLocation
-target_compile_definitions(nextcloudCore PRIVATE "QT_DISABLE_DEPRECATED_BEFORE=0")
-
-
-install(TARGETS ${APPLICATION_EXECUTABLE}
+install(TARGETS nextcloud
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
@@ -501,12 +521,12 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
set(NO_STRIP "")
endif()
- add_custom_command(TARGET ${APPLICATION_EXECUTABLE} POST_BUILD
+ add_custom_command(TARGET nextcloud POST_BUILD
COMMAND "${MACDEPLOYQT_EXECUTABLE}"
- "$/../.."
+ "$/../.."
-qmldir=${CMAKE_SOURCE_DIR}/src/gui
-always-overwrite
- -executable="$/${cmd_NAME}"
+ -executable="$/${cmd_NAME}"
${NO_STRIP}
COMMAND "${CMAKE_COMMAND}"
-E rm -rf "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/bearer"
@@ -517,13 +537,13 @@ endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop)
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${DATADIR}/applications )
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
configure_file(owncloud.xml.in ${APPLICATION_EXECUTABLE}.xml)
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${DATADIR}/mime/packages )
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages )
find_package(SharedMimeInfo)
if(SharedMimeInfo_FOUND)
- update_xdg_mimetypes( ${DATADIR}/mime/packages )
+ update_xdg_mimetypes( ${CMAKE_INSTALL_DATADIR}/mime/packages )
endif(SharedMimeInfo_FOUND)
endif()
diff --git a/src/gui/EmojiPicker.qml b/src/gui/EmojiPicker.qml
new file mode 100644
index 000000000000..6a66dbdcb190
--- /dev/null
+++ b/src/gui/EmojiPicker.qml
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+
+import com.nextcloud.desktopclient 1.0 as NC
+
+ColumnLayout {
+ NC.EmojiModel {
+ id: emojiModel
+ }
+
+ signal chosen(string emoji)
+
+ spacing: 0
+
+ FontMetrics {
+ id: metrics
+ }
+
+ ListView {
+ id: headerLayout
+ Layout.fillWidth: true
+ implicitWidth: contentItem.childrenRect.width
+ implicitHeight: metrics.height * 2
+
+ orientation: ListView.Horizontal
+
+ model: emojiModel.emojiCategoriesModel
+
+ delegate: ItemDelegate {
+ width: metrics.height * 2
+ height: headerLayout.height
+
+ contentItem: Text {
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: emoji
+ }
+
+ Rectangle {
+ anchors.bottom: parent.bottom
+
+ width: parent.width
+ height: 2
+
+ visible: ListView.isCurrentItem
+
+ color: "grey"
+ }
+
+
+ onClicked: {
+ emojiModel.setCategory(label)
+ }
+ }
+
+ }
+
+ Rectangle {
+ height: 1
+ Layout.fillWidth: true
+ color: "grey"
+ }
+
+ GridView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredHeight: metrics.height * 8
+
+ cellWidth: metrics.height * 2
+ cellHeight: metrics.height * 2
+
+ boundsBehavior: Flickable.DragOverBounds
+ clip: true
+
+ model: emojiModel.model
+
+ delegate: ItemDelegate {
+
+ width: metrics.height * 2
+ height: metrics.height * 2
+
+ contentItem: Text {
+ anchors.centerIn: parent
+ text: modelData === undefined ? "" : modelData.unicode
+ }
+
+ onClicked: {
+ chosen(modelData.unicode);
+ emojiModel.emojiUsed(modelData);
+ }
+ }
+
+ ScrollBar.vertical: ScrollBar {}
+
+ }
+
+}
diff --git a/src/gui/ErrorBox.qml b/src/gui/ErrorBox.qml
new file mode 100644
index 000000000000..8ef5d053c831
--- /dev/null
+++ b/src/gui/ErrorBox.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.15
+
+import Style 1.0
+
+Item {
+ id: errorBox
+
+ property var text: ""
+
+ property color color: Style.errorBoxTextColor
+ property color backgroundColor: Style.errorBoxBackgroundColor
+ property color borderColor: Style.errorBoxBorderColor
+
+ implicitHeight: errorMessage.implicitHeight + 2 * 8
+
+ Rectangle {
+ anchors.fill: parent
+ color: errorBox.backgroundColor
+ border.color: errorBox.borderColor
+ }
+
+ Text {
+ id: errorMessage
+
+ anchors.fill: parent
+ anchors.margins: 8
+ width: parent.width
+ color: errorBox.color
+ wrapMode: Text.WordWrap
+ text: errorBox.text
+ }
+}
diff --git a/src/gui/UserStatusSelector.qml b/src/gui/UserStatusSelector.qml
new file mode 100644
index 000000000000..82620a92006f
--- /dev/null
+++ b/src/gui/UserStatusSelector.qml
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+import QtQuick 2.6
+import QtQuick.Dialogs 1.3
+import QtQuick.Layouts 1.15
+import QtQuick.Controls 2.15
+import QtQuick.Window 2.15
+import com.nextcloud.desktopclient 1.0 as NC
+
+ColumnLayout {
+ id: rootLayout
+ spacing: 0
+ property NC.UserStatusSelectorModel userStatusSelectorModel
+
+ FontMetrics {
+ id: metrics
+ }
+
+ Text {
+ Layout.topMargin: 16
+ Layout.leftMargin: 8
+ Layout.rightMargin: 8
+ Layout.bottomMargin: 8
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ font.bold: true
+ text: qsTr("Online status")
+ }
+
+ GridLayout {
+ Layout.margins: 8
+ Layout.alignment: Qt.AlignTop
+ columns: 2
+ rows: 2
+ columnSpacing: 8
+ rowSpacing: 8
+
+ Button {
+ Layout.fillWidth: true
+ checked: NC.UserStatus.Online == userStatusSelectorModel.onlineStatus
+ checkable: true
+ icon.source: userStatusSelectorModel.onlineIcon
+ icon.color: "transparent"
+ text: qsTr("Online")
+ onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Online)
+ implicitWidth: 100
+ }
+ Button {
+ Layout.fillWidth: true
+ checked: NC.UserStatus.Away == userStatusSelectorModel.onlineStatus
+ checkable: true
+ icon.source: userStatusSelectorModel.awayIcon
+ icon.color: "transparent"
+ text: qsTr("Away")
+ onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Away)
+ implicitWidth: 100
+
+ }
+ Button {
+ Layout.fillWidth: true
+ checked: NC.UserStatus.DoNotDisturb == userStatusSelectorModel.onlineStatus
+ checkable: true
+ icon.source: userStatusSelectorModel.dndIcon
+ icon.color: "transparent"
+ text: qsTr("Do not disturb")
+ onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.DoNotDisturb)
+ implicitWidth: 100
+ }
+ Button {
+ Layout.fillWidth: true
+ checked: NC.UserStatus.Invisible == userStatusSelectorModel.onlineStatus
+ checkable: true
+ icon.source: userStatusSelectorModel.invisibleIcon
+ icon.color: "transparent"
+ text: qsTr("Invisible")
+ onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Invisible)
+ implicitWidth: 100
+ }
+ }
+
+ Text {
+ Layout.topMargin: 16
+ Layout.leftMargin: 8
+ Layout.rightMargin: 8
+ Layout.bottomMargin: 8
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ font.bold: true
+ text: qsTr("Status message")
+ }
+
+ RowLayout {
+ Layout.topMargin: 8
+ Layout.leftMargin: 8
+ Layout.rightMargin: 8
+ Layout.bottomMargin: 16
+ Layout.alignment: Qt.AlignTop
+ Layout.fillWidth: true
+
+ Button {
+ Layout.preferredWidth: userStatusMessageTextField.height // metrics.height * 2
+ Layout.preferredHeight: userStatusMessageTextField.height // metrics.height * 2
+ text: userStatusSelectorModel.userStatusEmoji
+ onClicked: emojiDialog.open()
+ }
+
+ Popup {
+ id: emojiDialog
+ padding: 0
+ margins: 0
+
+ anchors.centerIn: Overlay.overlay
+
+ EmojiPicker {
+ id: emojiPicker
+
+ onChosen: {
+ userStatusSelectorModel.userStatusEmoji = emoji
+ emojiDialog.close()
+ }
+ }
+ }
+
+ TextField {
+ id: userStatusMessageTextField
+ Layout.fillWidth: true
+ placeholderText: qsTr("What is your status?")
+ text: userStatusSelectorModel.userStatusMessage
+ selectByMouse: true
+ onEditingFinished: userStatusSelectorModel.setUserStatusMessage(text)
+ }
+ }
+
+ Repeater {
+ model: userStatusSelectorModel.predefinedStatusesCount
+
+ Button {
+ id: control
+ Layout.fillWidth: true
+ flat: !hovered
+ hoverEnabled: true
+ text: userStatusSelectorModel.predefinedStatus(index).icon + " " + userStatusSelectorModel.predefinedStatus(index).message + " - " + userStatusSelectorModel.predefinedStatusClearAt(index)
+ onClicked: userStatusSelectorModel.setPredefinedStatus(index)
+ }
+ }
+
+ RowLayout {
+ Layout.topMargin: 16
+ Layout.leftMargin: 8
+ Layout.rightMargin: 8
+ Layout.bottomMargin: 8
+ Layout.alignment: Qt.AlignTop
+
+ Text {
+ text: qsTr("Clear status message after")
+ }
+
+ ComboBox {
+ Layout.fillWidth: true
+ model: userStatusSelectorModel.clearAtValues
+ displayText: userStatusSelectorModel.clearAt
+ onActivated: userStatusSelectorModel.setClearAt(index)
+ }
+ }
+
+ RowLayout {
+ Layout.margins: 8
+ Layout.alignment: Qt.AlignTop
+
+ Button {
+ Layout.fillWidth: true
+ text: qsTr("Clear status message")
+ onClicked: userStatusSelectorModel.clearUserStatus()
+ }
+ Button {
+ highlighted: true
+ Layout.fillWidth: true
+ text: qsTr("Set status message")
+ onClicked: userStatusSelectorModel.setUserStatus()
+ }
+ }
+
+ ErrorBox {
+ Layout.margins: 8
+ Layout.fillWidth: true
+
+ visible: userStatusSelectorModel.errorMessage != ""
+ text: "Error: " + userStatusSelectorModel.errorMessage
+ }
+}
diff --git a/src/gui/UserStatusSelectorDialog.qml b/src/gui/UserStatusSelectorDialog.qml
new file mode 100644
index 000000000000..3f86f8cf9bd2
--- /dev/null
+++ b/src/gui/UserStatusSelectorDialog.qml
@@ -0,0 +1,27 @@
+import QtQuick.Window 2.15
+
+import com.nextcloud.desktopclient 1.0 as NC
+
+Window {
+ id: dialog
+
+ property NC.UserStatusSelectorModel model: NC.UserStatusSelectorModel {
+ onFinished: dialog.close()
+ }
+
+ minimumWidth: view.implicitWidth
+ minimumHeight: view.implicitHeight
+ maximumWidth: view.implicitWidth
+ maximumHeight: view.implicitHeight
+ width: maximumWidth
+ height: maximumHeight
+
+ visible: true
+
+ flags: Qt.Dialog
+
+ UserStatusSelector {
+ id: view
+ userStatusSelectorModel: model
+ }
+}
diff --git a/src/gui/accountmanager.h b/src/gui/accountmanager.h
index 9a1b50497162..0cec19053dc7 100644
--- a/src/gui/accountmanager.h
+++ b/src/gui/accountmanager.h
@@ -28,7 +28,7 @@ class AccountManager : public QObject
Q_OBJECT
public:
static AccountManager *instance();
- ~AccountManager() = default;
+ ~AccountManager() override = default;
/**
* Saves the accounts to a given settings file
diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp
index 43dab82a5769..76cf0cc39f28 100644
--- a/src/gui/accountsettings.cpp
+++ b/src/gui/accountsettings.cpp
@@ -593,6 +593,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
ac = menu->addAction(tr("Disable virtual file support …"));
connect(ac, &QAction::triggered, this, &AccountSettings::slotDisableVfsCurrentFolder);
+ ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder());
}
if (Theme::instance()->showVirtualFilesOption()
diff --git a/src/gui/accountsettings.h b/src/gui/accountsettings.h
index 17e8398394b5..a9908138f99f 100644
--- a/src/gui/accountsettings.h
+++ b/src/gui/accountsettings.h
@@ -55,7 +55,7 @@ class AccountSettings : public QWidget
public:
explicit AccountSettings(AccountState *accountState, QWidget *parent = nullptr);
- ~AccountSettings();
+ ~AccountSettings() override;
QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
bool canEncryptOrDecrypt(const FolderStatusModel::SubFolderInfo* folderInfo);
diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp
index bb2ab52738b2..7521dac799a7 100644
--- a/src/gui/accountstate.cpp
+++ b/src/gui/accountstate.cpp
@@ -44,7 +44,6 @@ AccountState::AccountState(AccountPtr account)
, _waitingForNewCredentials(false)
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
, _remoteWipe(new RemoteWipe(_account))
- , _userStatus(new UserStatus(this))
, _isDesktopNotificationsAllowed(true)
{
qRegisterMetaType("AccountState*");
@@ -127,26 +126,6 @@ void AccountState::setState(State state)
emit stateChanged(_state);
}
-UserStatus::Status AccountState::status() const
-{
- return _userStatus->status();
-}
-
-QString AccountState::statusMessage() const
-{
- return _userStatus->message();
-}
-
-QUrl AccountState::statusIcon() const
-{
- return _userStatus->icon();
-}
-
-QString AccountState::statusEmoji() const
-{
- return _userStatus->emoji();
-}
-
QString AccountState::stateString(State state)
{
switch (state) {
@@ -462,12 +441,6 @@ void AccountState::fetchNavigationApps(){
job->getNavigationApps();
}
-void AccountState::fetchUserStatus()
-{
- connect(_userStatus, &UserStatus::fetchUserStatusFinished, this, &AccountState::statusChanged);
- _userStatus->fetchUserStatus(_account);
-}
-
void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
if(statusCode == 200){
qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
diff --git a/src/gui/accountstate.h b/src/gui/accountstate.h
index 6249159a101c..7946e2f969f3 100644
--- a/src/gui/accountstate.h
+++ b/src/gui/accountstate.h
@@ -21,7 +21,7 @@
#include
#include "connectionvalidator.h"
#include "creds/abstractcredentials.h"
-#include "userstatus.h"
+
#include
class QSettings;
@@ -82,7 +82,7 @@ class AccountState : public QObject, public QSharedData
/// Use the account as parent
explicit AccountState(AccountPtr account);
- ~AccountState();
+ ~AccountState() override;
/** Creates an account state from settings and an Account object.
*
@@ -162,23 +162,6 @@ class AccountState : public QObject, public QSharedData
///Asks for user credentials
void handleInvalidCredentials();
- /** Returns the user status (Online, Dnd, Away, Offline, Invisible)
- * https://gist.github.com/georgehrke/55a0412007f13be1551d1f9436a39675
- */
- UserStatus::Status status() const;
-
- /** Returns the user status Message (text)
- */
- QString statusMessage() const;
-
- /** Returns the user status icon url
- */
- QUrl statusIcon() const;
-
- /** Returns the user status emoji
- */
- QString statusEmoji() const;
-
/** Returns the notifications status retrieved by the notificatons endpoint
* https://github.com/nextcloud/desktop/issues/2318#issuecomment-680698429
*/
@@ -188,10 +171,6 @@ class AccountState : public QObject, public QSharedData
*/
void setDesktopNotificationsAllowed(bool isAllowed);
- /** Fetch the user status (status, icon, message)
- */
- void fetchUserStatus();
-
public slots:
/// Triggers a ping to the server to update state and
/// connection status and errors.
@@ -256,7 +235,6 @@ protected Q_SLOTS:
*/
AccountAppList _apps;
- UserStatus *_userStatus;
bool _isDesktopNotificationsAllowed;
};
diff --git a/src/gui/addcertificatedialog.h b/src/gui/addcertificatedialog.h
index 158327b72720..bf7322ec89df 100644
--- a/src/gui/addcertificatedialog.h
+++ b/src/gui/addcertificatedialog.h
@@ -35,7 +35,7 @@ class AddCertificateDialog : public QDialog
public:
explicit AddCertificateDialog(QWidget *parent = nullptr);
- ~AddCertificateDialog();
+ ~AddCertificateDialog() override;
QString getCertificatePath();
QString getCertificatePasswd();
void showErrorMessage(const QString message);
diff --git a/src/gui/application.cpp b/src/gui/application.cpp
index 511da7558678..f153224b21fb 100644
--- a/src/gui/application.cpp
+++ b/src/gui/application.cpp
@@ -27,13 +27,14 @@
#include "folderman.h"
#include "logger.h"
#include "configfile.h"
-#include "socketapi.h"
+#include "socketapi/socketapi.h"
#include "sslerrordialog.h"
#include "theme.h"
#include "clientproxy.h"
#include "sharedialog.h"
#include "accountmanager.h"
#include "creds/abstractcredentials.h"
+#include "pushnotifications.h"
#if defined(BUILD_UPDATER)
#include "updater/ocupdater.h"
@@ -178,7 +179,7 @@ Application::Application(int &argc, char **argv)
, _showLogWindow(false)
, _logExpire(0)
, _logFlush(false)
- , _logDebug(false)
+ , _logDebug(true)
, _userTriggeredConnect(false)
, _debugMode(false)
, _backgroundMode(false)
@@ -349,6 +350,9 @@ Application::Application(int &argc, char **argv)
connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived,
_gui.data(), &ownCloudGui::slotShowShareDialog);
+ connect(FolderMan::instance()->socketApi(), &SocketApi::fileActivityCommandReceived,
+ Systray::instance(), &Systray::showFileActivityDialog);
+
// startup procedure.
connect(&_checkConnectionTimer, &QTimer::timeout, this, &Application::slotCheckConnection);
_checkConnectionTimer.setInterval(ConnectionValidator::DefaultCallingIntervalMsec); // check for connection every 32 seconds.
@@ -456,9 +460,10 @@ void Application::slotCheckConnection()
// Don't check if we're manually signed out or
// when the error is permanent.
- if (state != AccountState::SignedOut
- && state != AccountState::ConfigurationError
- && state != AccountState::AskingCredentials) {
+ const auto pushNotifications = accountState->account()->pushNotifications();
+ const auto pushNotificationsAvailable = (pushNotifications && pushNotifications->isReady());
+ if (state != AccountState::SignedOut && state != AccountState::ConfigurationError
+ && state != AccountState::AskingCredentials && !pushNotificationsAvailable) {
accountState->checkConnectivity();
}
}
@@ -524,7 +529,12 @@ void Application::setupLogging()
logger->enterNextLogFile();
- qCInfo(lcApplication) << QString::fromLatin1("################## %1 locale:[%2] ui_lang:[%3] version:[%4] os:[%5]").arg(_theme->appName()).arg(QLocale::system().name()).arg(property("ui_lang").toString()).arg(_theme->version()).arg(Utility::platformName());
+ qCInfo(lcApplication) << "##################" << _theme->appName()
+ << "locale:" << QLocale::system().name()
+ << "ui_lang:" << property("ui_lang")
+ << "version:" << _theme->version()
+ << "os:" << Utility::platformName();
+ qCInfo(lcApplication) << "Arguments:" << qApp->arguments();
}
void Application::slotUseMonoIconsChanged(bool)
diff --git a/src/gui/application.h b/src/gui/application.h
index aabaa63b023a..3f1436e65384 100644
--- a/src/gui/application.h
+++ b/src/gui/application.h
@@ -57,7 +57,7 @@ class Application : public SharedTools::QtSingleApplication
Q_OBJECT
public:
explicit Application(int &argc, char **argv);
- ~Application();
+ ~Application() override;
bool giveHelp();
void showHelp();
@@ -88,7 +88,7 @@ public slots:
void parseOptions(const QStringList &);
void setupTranslations();
void setupLogging();
- bool event(QEvent *event);
+ bool event(QEvent *event) override;
signals:
void folderRemoved();
diff --git a/src/gui/cloudproviders/cloudproviderwrapper.h b/src/gui/cloudproviders/cloudproviderwrapper.h
index 22caf362985c..58d00336e151 100644
--- a/src/gui/cloudproviders/cloudproviderwrapper.h
+++ b/src/gui/cloudproviders/cloudproviderwrapper.h
@@ -39,7 +39,7 @@ class CloudProviderWrapper : public QObject
Q_OBJECT
public:
explicit CloudProviderWrapper(QObject *parent = nullptr, Folder *folder = nullptr, int folderId = 0, CloudProvidersProviderExporter* cloudprovider = nullptr);
- ~CloudProviderWrapper();
+ ~CloudProviderWrapper() override;
CloudProvidersAccountExporter* accountExporter();
Folder* folder();
GMenuModel* getMenuModel();
diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp
index b94de0afd858..54b7b28a816b 100644
--- a/src/gui/creds/flow2auth.cpp
+++ b/src/gui/creds/flow2auth.cpp
@@ -100,7 +100,7 @@ void Flow2Auth::fetchNewToken(const TokenAction action)
pollToken = json.value("poll").toObject().value("token").toString();
pollEndpoint = json.value("poll").toObject().value("endpoint").toString();
if (_enforceHttps && QUrl(pollEndpoint).scheme() != QStringLiteral("https")) {
- qCWarning(lcFlow2auth) << "Can not poll endpoint because the returned url" << _pollEndpoint << "does not start with https";
+ qCWarning(lcFlow2auth) << "Can not poll endpoint because the returned url" << pollEndpoint << "does not start with https";
emit result(Error, tr("The polling URL does not start with HTTPS despite the login URL started with HTTPS. Login will not be possible because this might be a security issue. Please contact your administrator."));
return;
}
diff --git a/src/gui/creds/flow2auth.h b/src/gui/creds/flow2auth.h
index 6cb05c1d3968..3ac1cd0cd159 100644
--- a/src/gui/creds/flow2auth.h
+++ b/src/gui/creds/flow2auth.h
@@ -42,7 +42,7 @@ class Flow2Auth : public QObject
};
Flow2Auth(Account *account, QObject *parent);
- ~Flow2Auth();
+ ~Flow2Auth() override;
enum Result { NotSupported,
LoggedIn,
diff --git a/src/gui/creds/oauth.cpp b/src/gui/creds/oauth.cpp
index 2c0e20410a89..aa528aa49ce4 100644
--- a/src/gui/creds/oauth.cpp
+++ b/src/gui/creds/oauth.cpp
@@ -70,13 +70,14 @@ void OAuth::start()
QByteArray peek = socket->peek(qMin(socket->bytesAvailable(), 4000LL)); //The code should always be within the first 4K
if (peek.indexOf('\n') < 0)
return; // wait until we find a \n
- QRegExp rx("^GET /\\?code=([a-zA-Z0-9]+)[& ]"); // Match a /?code=... URL
- if (rx.indexIn(peek) != 0) {
+ const QRegularExpression rx("^GET /\\?code=([a-zA-Z0-9]+)[& ]"); // Match a /?code=... URL
+ const auto rxMatch = rx.match(peek);
+ if (!rxMatch.hasMatch()) {
httpReplyAndClose(socket, "404 Not Found", "404 Not Found404 Not Found
");
return;
}
- QString code = rx.cap(1); // The 'code' is the first capture of the regexp
+ QString code = rxMatch.captured(1); // The 'code' is the first capture of the regexp
QUrl requestToken = Utility::concatUrlPath(_account->url().toString(), QLatin1String("/index.php/apps/oauth2/api/v1/token"));
QNetworkRequest req;
diff --git a/src/gui/creds/oauth.h b/src/gui/creds/oauth.h
index 1c6b519e1331..0fa543b5e188 100644
--- a/src/gui/creds/oauth.h
+++ b/src/gui/creds/oauth.h
@@ -47,7 +47,7 @@ class OAuth : public QObject
, _account(account)
{
}
- ~OAuth();
+ ~OAuth() override;
enum Result { NotSupported,
LoggedIn,
diff --git a/src/gui/emojimodel.cpp b/src/gui/emojimodel.cpp
new file mode 100644
index 000000000000..e6b281db1ed2
--- /dev/null
+++ b/src/gui/emojimodel.cpp
@@ -0,0 +1,1571 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#include
+#include
+
+#include "emojimodel.h"
+
+namespace OCC {
+
+QVariant EmojiCategoriesModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) {
+ return {};
+ }
+
+ switch (role) {
+ case Roles::EmojiRole:
+ return categories[index.row()].emoji;
+
+ case Roles::LabelRole:
+ return categories[index.row()].label;
+ }
+
+ return {};
+}
+
+int EmojiCategoriesModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return static_cast(categories.size());
+}
+
+QHash EmojiCategoriesModel::roleNames() const
+{
+ QHash roles;
+ roles[Roles::EmojiRole] = "emoji";
+ roles[Roles::LabelRole] = "label";
+ return roles;
+}
+
+const std::vector EmojiCategoriesModel::categories = {
+ { "⌛️", "history" },
+ { "😏", "people" },
+ { "🌲", "nature" },
+ { "🍛", "food" },
+ { "🚁", "activity" },
+ { "🚅", "travel" },
+ { "💡", "objects" },
+ { "🔣", "symbols" },
+ { "🏁", "flags" },
+};
+
+QVariantList EmojiModel::history() const
+{
+ return _settings.value("Editor/emojis", QVariantList()).toList();
+}
+
+void EmojiModel::setCategory(const QString &category)
+{
+ if (_category == category) {
+ return;
+ }
+ _category = category;
+ emit modelChanged();
+}
+
+QAbstractListModel *EmojiModel::emojiCategoriesModel()
+{
+ return &_emojiCategoriesModel;
+}
+
+QVariantList EmojiModel::model() const
+{
+ if (_category == "history") {
+ return history();
+ } else if (_category == "people") {
+ return people;
+ } else if (_category == "nature") {
+ return nature;
+ } else if (_category == "food") {
+ return food;
+ } else if (_category == "activity") {
+ return activity;
+ } else if (_category == "travel") {
+ return travel;
+ } else if (_category == "objects") {
+ return objects;
+ } else if (_category == "symbols") {
+ return symbols;
+ } else if (_category == "flags") {
+ return flags;
+ }
+ return history();
+}
+
+void EmojiModel::emojiUsed(const QVariant &modelData)
+{
+ auto historyEmojis = history();
+
+ auto historyEmojisIter = historyEmojis.begin();
+ while (historyEmojisIter != historyEmojis.end()) {
+ if ((*historyEmojisIter).value().unicode == modelData.value().unicode) {
+ historyEmojisIter = historyEmojis.erase(historyEmojisIter);
+ } else {
+ historyEmojisIter++;
+ }
+ }
+
+ historyEmojis.push_front(modelData);
+ _settings.setValue("Editor/emojis", historyEmojis);
+
+ emit historyChanged();
+}
+
+const QVariantList EmojiModel::people = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x80"), ":grinning:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x81"), ":grin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x82"), ":joy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa3"), ":rofl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x83"), ":smiley:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x84"), ":smile:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x85"), ":sweat_smile:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x86"), ":laughing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x89"), ":wink:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8a"), ":blush:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8b"), ":yum:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8e"), ":sunglasses:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8d"), ":heart_eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x98"), ":kissing_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x97"), ":kissing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x99"), ":kissing_smiling_eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9a"), ":kissing_closed_eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xba"), ":relaxed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x82"), ":slight_smile:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x97"), ":hugging:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x94"), ":thinking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x90"), ":neutral_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x91"), ":expressionless:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb6"), ":no_mouth:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x84"), ":rolling_eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8f"), ":smirk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa3"), ":persevere:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa5"), ":disappointed_relieved:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xae"), ":open_mouth:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x90"), ":zipper_mouth:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xaf"), ":hushed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xaa"), ":sleepy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xab"), ":tired_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb4"), ":sleeping:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x8c"), ":relieved:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x93"), ":nerd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9b"), ":stuck_out_tongue:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9c"), ":stuck_out_tongue_winking_eye:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9d"), ":stuck_out_tongue_closed_eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa4"), ":drooling_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x92"), ":unamused:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x93"), ":sweat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x94"), ":pensive:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x95"), ":confused:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x83"), ":upside_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x91"), ":money_mouth:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb2"), ":astonished:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xb9"), ":frowning2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x81"), ":slight_frown:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x96"), ":confounded:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9e"), ":disappointed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x9f"), ":worried:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa4"), ":triumph:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa2"), ":cry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xad"), ":sob:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa6"), ":frowning:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa7"), ":anguished:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa8"), ":fearful:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa9"), ":weary:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xac"), ":grimacing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb0"), ":cold_sweat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb1"), ":scream:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb3"), ":flushed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb5"), ":dizzy_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa1"), ":rage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xa0"), ":angry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x87"), ":innocent:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa0"), ":cowboy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa1"), ":clown:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa5"), ":lying_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb7"), ":mask:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x92"), ":thermometer_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x95"), ":head_bandage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa2"), ":nauseated_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa7"), ":sneezing_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\x88"), ":smiling_imp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xbf"), ":imp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb9"), ":japanese_ogre:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xba"), ":japanese_goblin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x80"), ":skull:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xbb"), ":ghost:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xbd"), ":alien:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x96"), ":robot:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa9"), ":poop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xba"), ":smiley_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb8"), ":smile_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xb9"), ":joy_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xbb"), ":heart_eyes_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xbc"), ":smirk_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xbd"), ":kissing_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x80"), ":scream_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xbf"), ":crying_cat_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x98\xbe"), ":pouting_cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa6"), ":boy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa7"), ":girl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa8"), ":man:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa9"), ":woman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb4"), ":older_man:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb5"), ":older_woman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb6"), ":baby:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xbc"), ":angel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xae"), ":cop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb5"), ":spy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x82"), ":guardsman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb7"), ":construction_worker:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb3"), ":man_with_turban:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb1"), ":person_with_blond_hair:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x85"), ":santa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb6"), ":mrs_claus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb8"), ":princess:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb4"), ":prince:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb0"), ":bride_with_veil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb5"), ":man_in_tuxedo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb0"), ":pregnant_woman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xb2"), ":man_with_gua_pi_mao:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8d"), ":person_frowning:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8e"), ":person_with_pouting_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x85"), ":no_good:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x86"), ":ok_woman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x81"), ":information_desk_person:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8b"), ":raising_hand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x87"), ":bow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xa6"), ":face_palm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb7"), ":shrug:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x86"), ":massage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x87"), ":haircut:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb6"), ":walking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x83"), ":runner:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x83"), ":dancer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xba"), ":man_dancing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xaf"), ":dancers:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xa3"), ":speaking_head:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa4"), ":bust_in_silhouette:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa5"), ":busts_in_silhouette:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xab"), ":couple:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xac"), ":two_men_holding_hands:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xad"), ":two_women_holding_hands:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8f"), ":couplekiss:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x91"), ":couple_with_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xaa"), ":family:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xaa"), ":muscle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb3"), ":selfie:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x88"), ":point_left:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x89"), ":point_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x9d"), ":point_up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x86"), ":point_up_2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x95"), ":middle_finger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x87"), ":point_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x8c"), ":v:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x9e"), ":fingers_crossed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x96"), ":vulcan:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x98"), ":metal:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x99"), ":call_me:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x90"), ":hand_splayed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x8b"), ":raised_hand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8c"), ":ok_hand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8d"), ":thumbsup:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8e"), ":thumbsdown:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x8a"), ":fist:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8a"), ":punch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x9b"), ":left_facing_fist:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x9c"), ":right_facing_fist:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x9a"), ":raised_back_of_hand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8b"), ":wave:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x8f"), ":clap:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x8d"), ":writing_hand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x90"), ":open_hands:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8c"), ":raised_hands:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8f"), ":pray:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\x9d"), ":handshake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x85"), ":nail_care:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x82"), ":ear:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x83"), ":nose:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa3"), ":footprints:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x80"), ":eyes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x81"), ":eye:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x85"), ":tongue:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x84"), ":lips:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8b"), ":kiss:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa4"), ":zzz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x93"), ":eyeglasses:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb6"), ":dark_sunglasses:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x94"), ":necktie:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x95"), ":shirt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x96"), ":jeans:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x97"), ":dress:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x98"), ":kimono:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x99"), ":bikini:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9a"), ":womans_clothes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9b"), ":purse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9c"), ":handbag:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9d"), ":pouch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x92"), ":school_satchel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9e"), ":mans_shoe:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x9f"), ":athletic_shoe:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa0"), ":high_heel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa1"), ":sandal:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xa2"), ":boot:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x91"), ":crown:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x92"), ":womans_hat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa9"), ":tophat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x93"), ":mortar_board:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x91"), ":helmet_with_cross:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x84"), ":lipstick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8d"), ":ring:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x82"), ":closed_umbrella:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xbc"), ":briefcase:" }),
+};
+
+const QVariantList EmojiModel::nature = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x88"), ":see_no_evil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x89"), ":hear_no_evil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x99\x8a"), ":speak_no_evil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa6"), ":sweat_drops:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa8"), ":dash:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb5"), ":monkey_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x92"), ":monkey:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8d"), ":gorilla:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb6"), ":dog:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x95"), ":dog2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa9"), ":poodle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xba"), ":wolf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8a"), ":fox:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb1"), ":cat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x88"), ":cat2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x81"), ":lion_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xaf"), ":tiger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x85"), ":tiger2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x86"), ":leopard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb4"), ":horse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8e"), ":racehorse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8c"), ":deer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x84"), ":unicorn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xae"), ":cow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x82"), ":ox:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x83"), ":water_buffalo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x84"), ":cow2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb7"), ":pig:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x96"), ":pig2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x97"), ":boar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xbd"), ":pig_nose:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8f"), ":ram:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x91"), ":sheep:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x90"), ":goat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xaa"), ":dromedary_camel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xab"), ":camel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x98"), ":elephant:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8f"), ":rhino:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xad"), ":mouse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x81"), ":mouse2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x80"), ":rat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb9"), ":hamster:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb0"), ":rabbit:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x87"), ":rabbit2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xbf"), ":chipmunk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x87"), ":bat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xbb"), ":bear:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa8"), ":koala:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xbc"), ":panda_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xbe"), ":feet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x83"), ":turkey:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x94"), ":chicken:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x93"), ":rooster:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa3"), ":hatching_chick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa4"), ":baby_chick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa5"), ":hatched_chick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa6"), ":bird:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa7"), ":penguin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x8a"), ":dove:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x85"), ":eagle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x86"), ":duck:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x89"), ":owl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb8"), ":frog:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8a"), ":crocodile:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa2"), ":turtle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8e"), ":lizard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8d"), ":snake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb2"), ":dragon_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x89"), ":dragon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xb3"), ":whale:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8b"), ":whale2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xac"), ":dolphin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9f"), ":fish:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa0"), ":tropical_fish:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\xa1"), ":blowfish:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x88"), ":shark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x99"), ":octopus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9a"), ":shell:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x80"), ":crab:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x90"), ":shrimp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x91"), ":squid:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x8b"), ":butterfly:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x8c"), ":snail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9b"), ":bug:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9c"), ":ant:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9d"), ":bee:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x90\x9e"), ":beetle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb7"), ":spider:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb8"), ":spider_web:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa6\x82"), ":scorpion:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x90"), ":bouquet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb8"), ":cherry_blossom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb5"), ":rosette:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb9"), ":rose:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x80"), ":wilted_rose:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xba"), ":hibiscus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xbb"), ":sunflower:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xbc"), ":blossom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb7"), ":tulip:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb1"), ":seedling:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb2"), ":evergreen_tree:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb3"), ":deciduous_tree:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb4"), ":palm_tree:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb5"), ":cactus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xbe"), ":ear_of_rice:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xbf"), ":herb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x98"), ":shamrock:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x80"), ":four_leaf_clover:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x81"), ":maple_leaf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x82"), ":fallen_leaf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x83"), ":leaves:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x84"), ":mushroom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb0"), ":chestnut:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8d"), ":earth_africa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8e"), ":earth_americas:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8f"), ":earth_asia:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x91"), ":new_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x92"), ":waxing_crescent_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x93"), ":first_quarter_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x94"), ":waxing_gibbous_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x95"), ":full_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x96"), ":waning_gibbous_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x97"), ":last_quarter_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x98"), ":waning_crescent_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x99"), ":crescent_moon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9a"), ":new_moon_with_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9b"), ":first_quarter_moon_with_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9c"), ":last_quarter_moon_with_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x80"), ":sunny:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9d"), ":full_moon_with_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9e"), ":sun_with_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xad\x90"), ":star:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x9f"), ":star2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x81"), ":cloud:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x85"), ":partly_sunny:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x88"), ":thunder_cloud_rain:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa4"), ":white_sun_small_cloud:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa5"), ":white_sun_cloud:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa6"), ":white_sun_rain_cloud:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa7"), ":cloud_rain:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa8"), ":cloud_snow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa9"), ":cloud_lightning:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xaa"), ":cloud_tornado:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xab"), ":fog:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xac"), ":wind_blowing_face:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x82"), ":umbrella2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x94"), ":umbrella:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xa1"), ":zap:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x84"), ":snowflake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x83"), ":snowman2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x84"), ":snowman:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x84"), ":comet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa5"), ":fire:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa7"), ":droplet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8a"), ":ocean:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x83"), ":jack_o_lantern:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x84"), ":christmas_tree:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\xa8"), ":sparkles:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8b"), ":tanabata_tree:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8d"), ":bamboo:" }),
+};
+
+const QVariantList EmojiModel::food = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x87"), ":grapes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x88"), ":melon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x89"), ":watermelon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8a"), ":tangerine:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8b"), ":lemon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8c"), ":banana:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8d"), ":pineapple:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8e"), ":apple:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x8f"), ":green_apple:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x90"), ":pear:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x91"), ":peach:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x92"), ":cherries:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x93"), ":strawberry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x9d"), ":kiwi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x85"), ":tomato:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x91"), ":avocado:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x86"), ":eggplant:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x94"), ":potato:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x95"), ":carrot:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xbd"), ":corn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xb6"), ":hot_pepper:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x92"), ":cucumber:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x9c"), ":peanuts:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9e"), ":bread:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x90"), ":croissant:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x96"), ":french_bread:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x9e"), ":pancakes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa7\x80"), ":cheese:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x96"), ":meat_on_bone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x97"), ":poultry_leg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x93"), ":bacon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x94"), ":hamburger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9f"), ":fries:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x95"), ":pizza:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xad"), ":hotdog:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xae"), ":taco:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xaf"), ":burrito:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x99"), ":stuffed_flatbread:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x9a"), ":egg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb3"), ":cooking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x98"), ":shallow_pan_of_food:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb2"), ":stew:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x97"), ":salad:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xbf"), ":popcorn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb1"), ":bento:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x98"), ":rice_cracker:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x99"), ":rice_ball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9a"), ":rice:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9b"), ":curry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9c"), ":ramen:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\x9d"), ":spaghetti:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa0"), ":sweet_potato:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa2"), ":oden:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa3"), ":sushi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa4"), ":fried_shrimp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa5"), ":fish_cake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa1"), ":dango:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa6"), ":icecream:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa7"), ":shaved_ice:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa8"), ":ice_cream:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xa9"), ":doughnut:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xaa"), ":cookie:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x82"), ":birthday:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb0"), ":cake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xab"), ":chocolate_bar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xac"), ":candy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xad"), ":lollipop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xae"), ":custard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xaf"), ":honey_pot:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xbc"), ":baby_bottle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x9b"), ":milk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x95"), ":coffee:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb5"), ":tea:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb6"), ":sake:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xbe"), ":champagne:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb7"), ":wine_glass:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb8"), ":cocktail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb9"), ":tropical_drink:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xba"), ":beer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xbb"), ":beers:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x82"), ":champagne_glass:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x83"), ":tumbler_glass:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xbd"), ":fork_knife_plate:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8d\xb4"), ":fork_and_knife:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x84"), ":spoon:" }),
+};
+
+const QVariantList EmojiModel::activity = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\xbe"), ":space_invader:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb4"), ":levitate:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xba"), ":fencer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87"), ":horse_racing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbb"), ":horse_racing_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbc"), ":horse_racing_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbd"), ":horse_racing_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbe"), ":horse_racing_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbf"), ":horse_racing_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb7"), ":skier:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x82"), ":snowboarder:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8c"), ":golfer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84"), ":surfer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb"), ":surfer_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc"), ":surfer_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd"), ":surfer_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe"), ":surfer_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf"), ":surfer_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3"), ":rowboat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb"), ":rowboat_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc"), ":rowboat_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd"), ":rowboat_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe"), ":rowboat_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf"), ":rowboat_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a"), ":swimmer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb"), ":swimmer_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc"), ":swimmer_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd"), ":swimmer_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe"), ":swimmer_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf"), ":swimmer_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9"), ":basketball_player:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb"), ":basketball_player_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc"), ":basketball_player_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd"), ":basketball_player_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe"), ":basketball_player_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf"), ":basketball_player_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b"), ":lifter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb"), ":lifter_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc"), ":lifter_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd"), ":lifter_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe"), ":lifter_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf"), ":lifter_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4"), ":bicyclist:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb"), ":bicyclist_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc"), ":bicyclist_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd"), ":bicyclist_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe"), ":bicyclist_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf"), ":bicyclist_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5"), ":mountain_bicyclist:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb"), ":mountain_bicyclist_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc"), ":mountain_bicyclist_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd"), ":mountain_bicyclist_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe"), ":mountain_bicyclist_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf"), ":mountain_bicyclist_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8"), ":cartwheel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb"), ":cartwheel_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc"), ":cartwheel_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd"), ":cartwheel_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe"), ":cartwheel_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf"), ":cartwheel_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc"), ":wrestlers:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbb"), ":wrestlers_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbc"), ":wrestlers_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbd"), ":wrestlers_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbe"), ":wrestlers_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbf"), ":wrestlers_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd"), ":water_polo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb"), ":water_polo_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc"), ":water_polo_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd"), ":water_polo_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe"), ":water_polo_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf"), ":water_polo_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe"), ":handball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb"), ":handball_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc"), ":handball_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd"), ":handball_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe"), ":handball_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf"), ":handball_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9"), ":juggling:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb"), ":juggling_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc"), ":juggling_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd"), ":juggling_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe"), ":juggling_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf"), ":juggling_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xaa"), ":circus_tent:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xad"), ":performing_arts:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa8"), ":art:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb0"), ":slot_machine:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80"), ":bath:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbb"), ":bath_tone1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbc"), ":bath_tone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbd"), ":bath_tone3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbe"), ":bath_tone4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbf"), ":bath_tone5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x97"), ":reminder_ribbon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x9f"), ":tickets:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xab"), ":ticket:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x96"), ":military_medal:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x86"), ":trophy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x85"), ":medal:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x87"), ":first_place:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x88"), ":second_place:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x89"), ":third_place:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xbd"), ":soccer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xbe"), ":baseball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x80"), ":basketball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x90"), ":volleyball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x88"), ":football:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x89"), ":rugby_football:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xbe"), ":tennis:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb1"), ":8ball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb3"), ":bowling:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8f"), ":cricket:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x91"), ":field_hockey:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x92"), ":hockey:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x93"), ":ping_pong:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb8"), ":badminton:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x8a"), ":boxing_glove:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x8b"), ":martial_arts_uniform:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x85"), ":goal:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xaf"), ":dart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb3"), ":golf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb8"), ":ice_skate:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa3"), ":fishing_pole_and_fish:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xbd"), ":running_shirt_with_sash:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xbf"), ":ski:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xae"), ":video_game:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb2"), ":game_die:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xbc"), ":musical_score:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa4"), ":microphone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa7"), ":headphones:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb7"), ":saxophone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb8"), ":guitar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb9"), ":musical_keyboard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xba"), ":trumpet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xbb"), ":violin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\xa5\x81"), ":drum:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xac"), ":clapper:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb9"), ":bow_and_arrow:" }),
+};
+
+const QVariantList EmojiModel::travel = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8e"), ":race_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x8d"), ":motorcycle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xbe"), ":japan:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x94"), ":mountain_snow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb0"), ":mountain:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8b"), ":volcano:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xbb"), ":mount_fuji:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x95"), ":camping:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x96"), ":beach:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9c"), ":desert:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9d"), ":island:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9e"), ":park:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9f"), ":stadium:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9b"), ":classical_building:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x97"), ":construction_site:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x98"), ":homes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x99"), ":cityscape:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x9a"), ":house_abandoned:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa0"), ":house:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa1"), ":house_with_garden:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa2"), ":office:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa3"), ":post_office:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa4"), ":european_post_office:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa5"), ":hospital:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa6"), ":bank:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa8"), ":hotel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa9"), ":love_hotel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xaa"), ":convenience_store:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xab"), ":school:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xac"), ":department_store:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xad"), ":factory:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xaf"), ":japanese_castle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb0"), ":european_castle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x92"), ":wedding:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xbc"), ":tokyo_tower:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xbd"), ":statue_of_liberty:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xaa"), ":church:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x8c"), ":mosque:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x8d"), ":synagogue:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xa9"), ":shinto_shrine:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x8b"), ":kaaba:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb2"), ":fountain:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xba"), ":tent:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x81"), ":foggy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x83"), ":night_with_stars:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x84"), ":sunrise_over_mountains:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x85"), ":sunrise:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x86"), ":city_dusk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x87"), ":city_sunset:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x89"), ":bridge_at_night:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x8c"), ":milky_way:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa0"), ":carousel_horse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa1"), ":ferris_wheel:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa2"), ":roller_coaster:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x82"), ":steam_locomotive:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x83"), ":railway_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x84"), ":bullettrain_side:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x85"), ":bullettrain_front:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x86"), ":train2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x87"), ":metro:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x88"), ":light_rail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x89"), ":station:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8a"), ":tram:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9d"), ":monorail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9e"), ":mountain_railway:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8b"), ":train:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8c"), ":bus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8d"), ":oncoming_bus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8e"), ":trolleybus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x90"), ":minibus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x91"), ":ambulance:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x92"), ":fire_engine:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x93"), ":police_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x94"), ":oncoming_police_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x95"), ":taxi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x96"), ":oncoming_taxi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x97"), ":red_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x98"), ":oncoming_automobile:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x99"), ":blue_car:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9a"), ":truck:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9b"), ":articulated_lorry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9c"), ":tractor:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb2"), ":bike:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xb4"), ":scooter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xb5"), ":motor_scooter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x8f"), ":busstop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa3"), ":motorway:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa4"), ":railway_track:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xbd"), ":fuelpump:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa8"), ":rotating_light:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa5"), ":traffic_light:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa6"), ":vertical_traffic_light:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa7"), ":construction:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x93"), ":anchor:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb5"), ":sailboat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xb6"), ":canoe:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa4"), ":speedboat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xb3"), ":cruise_ship:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb4"), ":ferry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa5"), ":motorboat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa2"), ":ship:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x88"), ":airplane:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa9"), ":airplane_small:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xab"), ":airplane_departure:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xac"), ":airplane_arriving:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xba"), ":seat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x81"), ":helicopter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x9f"), ":suspension_railway:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa0"), ":mountain_cableway:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa1"), ":aerial_tramway:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\x80"), ":rocket:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xb0"), ":satellite_orbital:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa0"), ":stars:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x88"), ":rainbow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x86"), ":fireworks:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x87"), ":sparkler:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x91"), ":rice_scene:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\x81"), ":checkered_flag:" }),
+};
+
+const QVariantList EmojiModel::objects = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xa0"), ":skull_crossbones:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8c"), ":love_letter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa3"), ":bomb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb3"), ":hole:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x8d"), ":shopping_bags:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xbf"), ":prayer_beads:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8e"), ":gem:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xaa"), ":knife:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xba"), ":amphora:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xba"), ":map:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x88"), ":barber:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xbc"), ":frame_photo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x8e"), ":bellhop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xaa"), ":door:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x8c"), ":sleeping_accommodation:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x8f"), ":bed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x8b"), ":couch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xbd"), ":toilet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xbf"), ":shower:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x81"), ":bathtub:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8c\x9b"), ":hourglass:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb3"), ":hourglass_flowing_sand:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8c\x9a"), ":watch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb0"), ":alarm_clock:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb1"), ":stopwatch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb2"), ":timer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb0"), ":clock:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\xa1"), ":thermometer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\xb1"), ":beach_umbrella:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x88"), ":balloon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x89"), ":tada:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8a"), ":confetti_ball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8e"), ":dolls:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8f"), ":flags:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x90"), ":wind_chime:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x80"), ":ribbon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x81"), ":gift:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xb9"), ":joystick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xaf"), ":postal_horn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x99"), ":microphone2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x9a"), ":level_slider:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x9b"), ":control_knobs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xbb"), ":radio:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb1"), ":iphone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb2"), ":calling:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x8e"), ":telephone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9e"), ":telephone_receiver:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9f"), ":pager:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa0"), ":fax:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8b"), ":battery:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8c"), ":electric_plug:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xbb"), ":computer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xa5"), ":desktop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xa8"), ":printer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8c\xa8"), ":keyboard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xb1"), ":mouse_three_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xb2"), ":trackball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xbd"), ":minidisc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xbe"), ":floppy_disk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xbf"), ":cd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x80"), ":dvd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa5"), ":movie_camera:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x9e"), ":film_frames:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xbd"), ":projector:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xba"), ":tv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb7"), ":camera:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb8"), ":camera_with_flash:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb9"), ":video_camera:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xbc"), ":vhs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8d"), ":mag:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8e"), ":mag_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xac"), ":microscope:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xad"), ":telescope:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa1"), ":satellite:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xaf"), ":candle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa1"), ":bulb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa6"), ":flashlight:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xae"), ":izakaya_lantern:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x94"), ":notebook_with_decorative_cover:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x95"), ":closed_book:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x96"), ":book:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x97"), ":green_book:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x98"), ":blue_book:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x99"), ":orange_book:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9a"), ":books:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x93"), ":notebook:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x92"), ":ledger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x83"), ":page_with_curl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9c"), ":scroll:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x84"), ":page_facing_up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb0"), ":newspaper:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x9e"), ":newspaper2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x91"), ":bookmark_tabs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x96"), ":bookmark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb7"), ":label:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb0"), ":moneybag:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb4"), ":yen:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb5"), ":dollar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb6"), ":euro:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb7"), ":pound:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb8"), ":money_with_wings:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb3"), ":credit_card:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x89"), ":envelope:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa7"), ":e-mail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa8"), ":incoming_envelope:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa9"), ":envelope_with_arrow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa4"), ":outbox_tray:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa5"), ":inbox_tray:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa6"), ":package:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xab"), ":mailbox:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xaa"), ":mailbox_closed:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xac"), ":mailbox_with_mail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xad"), ":mailbox_with_no_mail:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xae"), ":postbox:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xb3"), ":ballot_box:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x8f"), ":pencil2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x92"), ":black_nib:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x8b"), ":pen_fountain:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x8a"), ":pen_ballpoint:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x8c"), ":paintbrush:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x8d"), ":crayon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9d"), ":pencil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x81"), ":file_folder:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x82"), ":open_file_folder:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x82"), ":dividers:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x85"), ":date:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x86"), ":calendar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x92"), ":notepad_spiral:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x93"), ":calendar_spiral:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x87"), ":card_index:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x88"), ":chart_with_upwards_trend:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x89"), ":chart_with_downwards_trend:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8a"), ":bar_chart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8b"), ":clipboard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8c"), ":pushpin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8d"), ":round_pushpin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8e"), ":paperclip:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\x87"), ":paperclips:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x8f"), ":straight_ruler:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x90"), ":triangular_ruler:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x82"), ":scissors:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x83"), ":card_box:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x84"), ":file_cabinet:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x91"), ":wastebasket:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x92"), ":lock:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x93"), ":unlock:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8f"), ":lock_with_ink_pen:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x90"), ":closed_lock_with_key:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x91"), ":key:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x9d"), ":key2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa8"), ":hammer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x8f"), ":pick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x92"), ":hammer_pick:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa0"), ":tools:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xa1"), ":dagger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x94"), ":crossed_swords:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xab"), ":gun:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa1"), ":shield:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa7"), ":wrench:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa9"), ":nut_and_bolt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x99"), ":gear:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\x9c"), ":compression:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x97"), ":alembic:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x96"), ":scales:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x97"), ":link:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x93"), ":chains:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x89"), ":syringe:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x8a"), ":pill:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xac"), ":smoking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xb0"), ":coffin:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xb1"), ":urn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xbf"), ":moyai:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\xa2"), ":oil:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xae"), ":crystal_ball:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x92"), ":shopping_cart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xa9"), ":triangular_flag_on_post:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\x8c"), ":crossed_flags:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb4"), ":flag_black:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb3"), ":flag_white:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xb3\xf0\x9f\x8c\x88"), ":rainbow_flag:" }),
+};
+
+const QVariantList EmojiModel::symbols = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x91\x81\xf0\x9f\x97\xa8"), ":eye_in_speech_bubble:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x98"), ":cupid:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\xa4"), ":heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x93"), ":heartbeat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x94"), ":broken_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x95"), ":two_hearts:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x96"), ":sparkling_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x97"), ":heartpulse:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x99"), ":blue_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9a"), ":green_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9b"), ":yellow_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9c"), ":purple_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x96\xa4"), ":black_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9d"), ":gift_heart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9e"), ":revolving_hearts:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\x9f"), ":heart_decoration:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\xa3"), ":heart_exclamation:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa2"), ":anger:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa5"), ":boom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xab"), ":dizzy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xac"), ":speech_balloon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xa8"), ":speech_left:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x97\xaf"), ":anger_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xad"), ":thought_balloon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xae"), ":white_flower:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x90"), ":globe_with_meridians:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xa8"), ":hotsprings:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x91"), ":octagonal_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9b"), ":clock12:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa7"), ":clock1230:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x90"), ":clock1:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9c"), ":clock130:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x91"), ":clock2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9d"), ":clock230:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x92"), ":clock3:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9e"), ":clock330:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x93"), ":clock4:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9f"), ":clock430:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x94"), ":clock5:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa0"), ":clock530:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x95"), ":clock6:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa1"), ":clock630:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x96"), ":clock7:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa2"), ":clock730:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x97"), ":clock8:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa3"), ":clock830:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x98"), ":clock9:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa4"), ":clock930:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x99"), ":clock10:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa5"), ":clock1030:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x9a"), ":clock11:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\xa6"), ":clock1130:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8c\x80"), ":cyclone:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xa0"), ":spades:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xa5"), ":hearts:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xa6"), ":diamonds:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xa3"), ":clubs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x83\x8f"), ":black_joker:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x80\x84"), ":mahjong:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb4"), ":flower_playing_cards:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x87"), ":mute:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x88"), ":speaker:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x89"), ":sound:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x8a"), ":loud_sound:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa2"), ":loudspeaker:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xa3"), ":mega:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x94"), ":bell:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x95"), ":no_bell:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb5"), ":musical_note:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xb6"), ":notes:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb9"), ":chart:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb1"), ":currency_exchange:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xb2"), ":heavy_dollar_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8f\xa7"), ":atm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xae"), ":put_litter_in_its_place:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb0"), ":potable_water:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xbf"), ":wheelchair:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb9"), ":mens:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xba"), ":womens:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xbb"), ":restroom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xbc"), ":baby_symbol:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xbe"), ":wc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x82"), ":passport_control:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x83"), ":customs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x84"), ":baggage_claim:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x85"), ":left_luggage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xa0"), ":warning:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb8"), ":children_crossing:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x94"), ":no_entry:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xab"), ":no_entry_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb3"), ":no_bicycles:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xad"), ":no_smoking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xaf"), ":do_not_litter:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb1"), ":non-potable_water:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9a\xb7"), ":no_pedestrians:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb5"), ":no_mobile_phones:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9e"), ":underage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xa2"), ":radioactive:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xa3"), ":biohazard:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xac\x86"), ":arrow_up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x97"), ":arrow_upper_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\xa1"), ":arrow_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x98"), ":arrow_lower_right:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xac\x87"), ":arrow_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x99"), ":arrow_lower_left:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xac\x85"), ":arrow_left:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x96"), ":arrow_upper_left:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x95"), ":arrow_up_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\x94"), ":left_right_arrow:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\xa9"), ":leftwards_arrow_with_hook:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x86\xaa"), ":arrow_right_hook:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xa4\xb4"), ":arrow_heading_up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xa4\xb5"), ":arrow_heading_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x83"), ":arrows_clockwise:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x84"), ":arrows_counterclockwise:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x99"), ":back:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9a"), ":end:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9b"), ":on:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9c"), ":soon:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9d"), ":top:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x9b\x90"), ":place_of_worship:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x9b"), ":atom:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x89"), ":om_symbol:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\xa1"), ":star_of_david:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xb8"), ":wheel_of_dharma:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xaf"), ":yin_yang:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x9d"), ":cross:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xa6"), ":orthodox_cross:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xaa"), ":star_and_crescent:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\xae"), ":peace:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x95\x8e"), ":menorah:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xaf"), ":six_pointed_star:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x88"), ":aries:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x89"), ":taurus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8a"), ":gemini:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8b"), ":cancer:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8c"), ":leo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8d"), ":virgo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8e"), ":libra:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x8f"), ":scorpius:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x90"), ":sagittarius:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x91"), ":capricorn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x92"), ":aquarius:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\x93"), ":pisces:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9b\x8e"), ":ophiuchus:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x80"), ":twisted_rightwards_arrows:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x81"), ":repeat:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x82"), ":repeat_one:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x96\xb6"), ":arrow_forward:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xa9"), ":fast_forward:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xad"), ":track_next:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xaf"), ":play_pause:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x97\x80"), ":arrow_backward:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xaa"), ":rewind:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xae"), ":track_previous:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xbc"), ":arrow_up_small:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xab"), ":arrow_double_up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xbd"), ":arrow_down_small:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xac"), ":arrow_double_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb8"), ":pause_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xb9"), ":stop_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\xba"), ":record_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x8f\x8f"), ":eject:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x8e\xa6"), ":cinema:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x85"), ":low_brightness:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x86"), ":high_brightness:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb6"), ":signal_strength:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb3"), ":vibration_mode:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\xb4"), ":mobile_phone_off:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x99\xbb"), ":recycle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x93\x9b"), ":name_badge:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\x9c"), ":fleur-de-lis:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb0"), ":beginner:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb1"), ":trident:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xad\x95"), ":o:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x85"), ":white_check_mark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x98\x91"), ":ballot_box_with_check:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x94"), ":heavy_check_mark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\x96"), ":heavy_multiplication_x:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x8c"), ":x:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x8e"), ":negative_squared_cross_mark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\x95"), ":heavy_plus_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\x96"), ":heavy_minus_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\x97"), ":heavy_division_sign:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\xb0"), ":curly_loop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9e\xbf"), ":loop:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe3\x80\xbd"), ":part_alternation_mark:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\xb3"), ":eight_spoked_asterisk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9c\xb4"), ":eight_pointed_black_star:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x87"), ":sparkle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x80\xbc"), ":bangbang:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x81\x89"), ":interrobang:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x93"), ":question:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x94"), ":grey_question:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x95"), ":grey_exclamation:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9d\x97"), ":exclamation:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe3\x80\xb0"), ":wavy_dash:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xc2\xa9"), ":copyright:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xc2\xae"), ":registered:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x84\xa2"), ":tm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("#\xe2\x83\xa3"), ":hash:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("*\xe2\x83\xa3"), ":asterisk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("0\xe2\x83\xa3"), ":zero:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("1\xe2\x83\xa3"), ":one:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("2\xe2\x83\xa3"), ":two:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("3\xe2\x83\xa3"), ":three:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("4\xe2\x83\xa3"), ":four:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("5\xe2\x83\xa3"), ":five:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("6\xe2\x83\xa3"), ":six:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("7\xe2\x83\xa3"), ":seven:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("8\xe2\x83\xa3"), ":eight:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("9\xe2\x83\xa3"), ":nine:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x9f"), ":keycap_ten:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xaf"), ":100:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa0"), ":capital_abcd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa1"), ":abcd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa2"), ":1234:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa3"), ":symbols:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xa4"), ":abc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x85\xb0"), ":a:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x8e"), ":ab:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x85\xb1"), ":b:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x91"), ":cl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x92"), ":cool:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x93"), ":free:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x84\xb9"), ":information_source:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x94"), ":id:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x93\x82"), ":m:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x95"), ":new:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x96"), ":ng:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x85\xbe"), ":o2:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x97"), ":ok:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x85\xbf"), ":parking:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x98"), ":sos:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x99"), ":up:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x86\x9a"), ":vs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\x81"), ":koko:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\x82"), ":sa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb7"), ":u6708:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb6"), ":u6709:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xaf"), ":u6307:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x89\x90"), ":ideograph_advantage:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb9"), ":u5272:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\x9a"), ":u7121:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb2"), ":u7981:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x89\x91"), ":accept:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb8"), ":u7533:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb4"), ":u5408:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb3"), ":u7a7a:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe3\x8a\x97"), ":congratulations:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe3\x8a\x99"), ":secret:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xba"), ":u55b6:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x88\xb5"), ":u6e80:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x96\xaa"), ":black_small_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x96\xab"), ":white_small_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x97\xbb"), ":white_medium_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x97\xbc"), ":black_medium_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x97\xbd"), ":white_medium_small_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x97\xbe"), ":black_medium_small_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xac\x9b"), ":black_large_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\xac\x9c"), ":white_large_square:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb6"), ":large_orange_diamond:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb7"), ":large_blue_diamond:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb8"), ":small_orange_diamond:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb9"), ":small_blue_diamond:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xba"), ":small_red_triangle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xbb"), ":small_red_triangle_down:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x92\xa0"), ":diamond_shape_with_a_dot_inside:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\x98"), ":radio_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb2"), ":black_square_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb3"), ":white_square_button:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xaa"), ":white_circle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xe2\x9a\xab"), ":black_circle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb4"), ":red_circle:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x94\xb5"), ":blue_circle:" }),
+};
+
+const QVariantList EmojiModel::flags = {
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa8"), ":flag_ac:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa9"), ":flag_ad:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xaa"), ":flag_ae:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xab"), ":flag_af:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xac"), ":flag_ag:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xae"), ":flag_ai:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb1"), ":flag_al:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb2"), ":flag_am:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb4"), ":flag_ao:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb6"), ":flag_aq:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb7"), ":flag_ar:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb8"), ":flag_as:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb9"), ":flag_at:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xba"), ":flag_au:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbc"), ":flag_aw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbd"), ":flag_ax:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbf"), ":flag_az:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa6"), ":flag_ba:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa7"), ":flag_bb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa9"), ":flag_bd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaa"), ":flag_be:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xab"), ":flag_bf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xac"), ":flag_bg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xad"), ":flag_bh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xae"), ":flag_bi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaf"), ":flag_bj:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb1"), ":flag_bl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb2"), ":flag_bm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb3"), ":flag_bn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb4"), ":flag_bo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb6"), ":flag_bq:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb7"), ":flag_br:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb8"), ":flag_bs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb9"), ":flag_bt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbb"), ":flag_bv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbc"), ":flag_bw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbe"), ":flag_by:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbf"), ":flag_bz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa6"), ":flag_ca:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa8"), ":flag_cc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa9"), ":flag_cd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xab"), ":flag_cf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xac"), ":flag_cg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xad"), ":flag_ch:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xae"), ":flag_ci:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb0"), ":flag_ck:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb1"), ":flag_cl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb2"), ":flag_cm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb3"), ":flag_cn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb4"), ":flag_co:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb5"), ":flag_cp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb7"), ":flag_cr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xba"), ":flag_cu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbb"), ":flag_cv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbc"), ":flag_cw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbd"), ":flag_cx:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbe"), ":flag_cy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbf"), ":flag_cz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaa"), ":flag_de:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xac"), ":flag_dg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaf"), ":flag_dj:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb0"), ":flag_dk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb2"), ":flag_dm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb4"), ":flag_do:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xbf"), ":flag_dz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa6"), ":flag_ea:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa8"), ":flag_ec:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xaa"), ":flag_ee:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xac"), ":flag_eg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xad"), ":flag_eh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb7"), ":flag_er:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb8"), ":flag_es:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb9"), ":flag_et:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"), ":flag_eu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xae"), ":flag_fi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xaf"), ":flag_fj:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb0"), ":flag_fk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb2"), ":flag_fm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb4"), ":flag_fo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb7"), ":flag_fr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa6"), ":flag_ga:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"), ":flag_gb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa9"), ":flag_gd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xaa"), ":flag_ge:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xab"), ":flag_gf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xac"), ":flag_gg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xad"), ":flag_gh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xae"), ":flag_gi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb1"), ":flag_gl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb2"), ":flag_gm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb3"), ":flag_gn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb5"), ":flag_gp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb6"), ":flag_gq:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb7"), ":flag_gr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb8"), ":flag_gs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb9"), ":flag_gt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xba"), ":flag_gu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbc"), ":flag_gw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbe"), ":flag_gy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb0"), ":flag_hk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb2"), ":flag_hm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb3"), ":flag_hn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb7"), ":flag_hr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb9"), ":flag_ht:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xba"), ":flag_hu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa8"), ":flag_ic:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa9"), ":flag_id:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xaa"), ":flag_ie:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb1"), ":flag_il:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb2"), ":flag_im:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb3"), ":flag_in:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb4"), ":flag_io:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb6"), ":flag_iq:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb7"), ":flag_ir:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb8"), ":flag_is:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb9"), ":flag_it:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xaa"), ":flag_je:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb2"), ":flag_jm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb4"), ":flag_jo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb5"), ":flag_jp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xaa"), ":flag_ke:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xac"), ":flag_kg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xad"), ":flag_kh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xae"), ":flag_ki:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb2"), ":flag_km:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb3"), ":flag_kn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb5"), ":flag_kp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb7"), ":flag_kr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbc"), ":flag_kw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbe"), ":flag_ky:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbf"), ":flag_kz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa6"), ":flag_la:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa7"), ":flag_lb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa8"), ":flag_lc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xae"), ":flag_li:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb0"), ":flag_lk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb7"), ":flag_lr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb8"), ":flag_ls:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb9"), ":flag_lt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xba"), ":flag_lu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbb"), ":flag_lv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbe"), ":flag_ly:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa6"), ":flag_ma:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa8"), ":flag_mc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa9"), ":flag_md:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xaa"), ":flag_me:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xab"), ":flag_mf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xac"), ":flag_mg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xad"), ":flag_mh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb0"), ":flag_mk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb1"), ":flag_ml:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb2"), ":flag_mm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb3"), ":flag_mn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb4"), ":flag_mo:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb5"), ":flag_mp:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb6"), ":flag_mq:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb7"), ":flag_mr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb8"), ":flag_ms:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb9"), ":flag_mt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xba"), ":flag_mu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbb"), ":flag_mv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbc"), ":flag_mw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbd"), ":flag_mx:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbe"), ":flag_my:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbf"), ":flag_mz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa6"), ":flag_na:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa8"), ":flag_nc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xaa"), ":flag_ne:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xab"), ":flag_nf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xac"), ":flag_ng:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xae"), ":flag_ni:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb1"), ":flag_nl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb4"), ":flag_no:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb5"), ":flag_np:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb7"), ":flag_nr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xba"), ":flag_nu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xbf"), ":flag_nz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb4\xf0\x9f\x87\xb2"), ":flag_om:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xa6"), ":flag_pa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xaa"), ":flag_pe:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xab"), ":flag_pf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xac"), ":flag_pg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xad"), ":flag_ph:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb0"), ":flag_pk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb1"), ":flag_pl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb2"), ":flag_pm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb3"), ":flag_pn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb7"), ":flag_pr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb8"), ":flag_ps:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb9"), ":flag_pt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbc"), ":flag_pw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbe"), ":flag_py:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb6\xf0\x9f\x87\xa6"), ":flag_qa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xaa"), ":flag_re:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb4"), ":flag_ro:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb8"), ":flag_rs:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xba"), ":flag_ru:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xbc"), ":flag_rw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa6"), ":flag_sa:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa7"), ":flag_sb:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa8"), ":flag_sc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa9"), ":flag_sd:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaa"), ":flag_se:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xac"), ":flag_sg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xad"), ":flag_sh:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xae"), ":flag_si:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaf"), ":flag_sj:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb0"), ":flag_sk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb1"), ":flag_sl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb2"), ":flag_sm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb3"), ":flag_sn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb4"), ":flag_so:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb7"), ":flag_sr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb8"), ":flag_ss:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb9"), ":flag_st:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbb"), ":flag_sv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbd"), ":flag_sx:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbe"), ":flag_sy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbf"), ":flag_sz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa6"), ":flag_ta:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa8"), ":flag_tc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa9"), ":flag_td:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xab"), ":flag_tf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xac"), ":flag_tg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xad"), ":flag_th:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xaf"), ":flag_tj:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb0"), ":flag_tk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb1"), ":flag_tl:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb2"), ":flag_tm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb3"), ":flag_tn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb4"), ":flag_to:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb7"), ":flag_tr:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb9"), ":flag_tt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbb"), ":flag_tv:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbc"), ":flag_tw:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbf"), ":flag_tz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xa6"), ":flag_ua:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xac"), ":flag_ug:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb2"), ":flag_um:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"), ":flag_us:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbe"), ":flag_uy:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbf"), ":flag_uz:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa6"), ":flag_va:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa8"), ":flag_vc:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xaa"), ":flag_ve:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xac"), ":flag_vg:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xae"), ":flag_vi:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xb3"), ":flag_vn:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xba"), ":flag_vu:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xab"), ":flag_wf:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xb8"), ":flag_ws:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbd\xf0\x9f\x87\xb0"), ":flag_xk:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xaa"), ":flag_ye:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xb9"), ":flag_yt:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xa6"), ":flag_za:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xb2"), ":flag_zm:" }),
+ QVariant::fromValue(Emoji { QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xbc"), ":flag_zw:" }),
+};
+}
diff --git a/src/gui/emojimodel.h b/src/gui/emojimodel.h
new file mode 100644
index 000000000000..2d35305d4644
--- /dev/null
+++ b/src/gui/emojimodel.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace OCC {
+
+struct Emoji
+{
+ Emoji(QString u, QString s, bool isCustom = false)
+ : unicode(std::move(std::move(u)))
+ , shortname(std::move(std::move(s)))
+ , isCustom(isCustom)
+ {
+ }
+ Emoji() = default;
+
+ friend QDataStream &operator<<(QDataStream &arch, const Emoji &object)
+ {
+ arch << object.unicode;
+ arch << object.shortname;
+ return arch;
+ }
+
+ friend QDataStream &operator>>(QDataStream &arch, Emoji &object)
+ {
+ arch >> object.unicode;
+ arch >> object.shortname;
+ object.isCustom = object.unicode.startsWith("image://");
+ return arch;
+ }
+
+ QString unicode;
+ QString shortname;
+ bool isCustom = false;
+
+ Q_GADGET
+ Q_PROPERTY(QString unicode MEMBER unicode)
+ Q_PROPERTY(QString shortname MEMBER shortname)
+ Q_PROPERTY(bool isCustom MEMBER isCustom)
+};
+
+class EmojiCategoriesModel : public QAbstractListModel
+{
+public:
+ QVariant data(const QModelIndex &index, int role) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash roleNames() const override;
+
+private:
+ enum Roles {
+ EmojiRole = 0,
+ LabelRole
+ };
+
+ struct Category
+ {
+ QString emoji;
+ QString label;
+ };
+
+ static const std::vector categories;
+};
+
+class EmojiModel : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariantList model READ model NOTIFY modelChanged)
+ Q_PROPERTY(QAbstractListModel *emojiCategoriesModel READ emojiCategoriesModel CONSTANT)
+
+ Q_PROPERTY(QVariantList history READ history NOTIFY historyChanged)
+
+ Q_PROPERTY(QVariantList people MEMBER people CONSTANT)
+ Q_PROPERTY(QVariantList nature MEMBER nature CONSTANT)
+ Q_PROPERTY(QVariantList food MEMBER food CONSTANT)
+ Q_PROPERTY(QVariantList activity MEMBER activity CONSTANT)
+ Q_PROPERTY(QVariantList travel MEMBER travel CONSTANT)
+ Q_PROPERTY(QVariantList objects MEMBER objects CONSTANT)
+ Q_PROPERTY(QVariantList symbols MEMBER symbols CONSTANT)
+ Q_PROPERTY(QVariantList flags MEMBER flags CONSTANT)
+
+public:
+ explicit EmojiModel(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ }
+
+ Q_INVOKABLE QVariantList history() const;
+ Q_INVOKABLE void setCategory(const QString &category);
+ Q_INVOKABLE void emojiUsed(const QVariant &modelData);
+
+ QVariantList model() const;
+ QAbstractListModel *emojiCategoriesModel();
+
+signals:
+ void historyChanged();
+ void modelChanged();
+
+private:
+ static const QVariantList people;
+ static const QVariantList nature;
+ static const QVariantList food;
+ static const QVariantList activity;
+ static const QVariantList travel;
+ static const QVariantList objects;
+ static const QVariantList symbols;
+ static const QVariantList flags;
+
+ QSettings _settings;
+ QString _category = "history";
+
+ EmojiCategoriesModel _emojiCategoriesModel;
+};
+
+}
+
+Q_DECLARE_METATYPE(OCC::Emoji)
diff --git a/src/gui/fileactivitylistmodel.cpp b/src/gui/fileactivitylistmodel.cpp
new file mode 100644
index 000000000000..104ff317c291
--- /dev/null
+++ b/src/gui/fileactivitylistmodel.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#include "fileactivitylistmodel.h"
+#include "folderman.h"
+#include "tray/activitylistmodel.h"
+
+namespace OCC {
+
+Q_LOGGING_CATEGORY(lcFileActivityListModel, "nextcloud.gui.fileactivitylistmodel", QtInfoMsg)
+
+FileActivityListModel::FileActivityListModel(QObject *parent)
+ : ActivityListModel(nullptr, parent)
+{
+ setDisplayActions(false);
+}
+
+void FileActivityListModel::load(AccountState *accountState, const QString &localPath)
+{
+ Q_ASSERT(accountState);
+ if (!accountState || currentlyFetching()) {
+ return;
+ }
+ setAccountState(accountState);
+
+ const auto folder = FolderMan::instance()->folderForPath(localPath);
+ if (!folder) {
+ return;
+ }
+
+ const auto file = folder->fileFromLocalPath(localPath);
+ SyncJournalFileRecord fileRecord;
+ if (!folder->journalDb()->getFileRecord(file, &fileRecord) || !fileRecord.isValid()) {
+ return;
+ }
+
+ _fileId = fileRecord._fileId;
+ slotRefreshActivity();
+}
+
+void FileActivityListModel::startFetchJob()
+{
+ if (!accountState()->isConnected()) {
+ return;
+ }
+ setCurrentlyFetching(true);
+
+ const QString url(QStringLiteral("ocs/v2.php/apps/activity/api/v2/activity/filter"));
+ auto job = new JsonApiJob(accountState()->account(), url, this);
+ QObject::connect(job, &JsonApiJob::jsonReceived,
+ this, &FileActivityListModel::activitiesReceived);
+
+ QUrlQuery params;
+ params.addQueryItem(QStringLiteral("sort"), QStringLiteral("asc"));
+ params.addQueryItem(QStringLiteral("object_type"), "files");
+ params.addQueryItem(QStringLiteral("object_id"), _fileId);
+ job->addQueryParams(params);
+ setDoneFetching(true);
+ setHideOldActivities(true);
+ job->start();
+}
+}
diff --git a/src/gui/fileactivitylistmodel.h b/src/gui/fileactivitylistmodel.h
new file mode 100644
index 000000000000..421c58128618
--- /dev/null
+++ b/src/gui/fileactivitylistmodel.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "accountstate.h"
+#include "tray/activitylistmodel.h"
+
+namespace OCC {
+
+class FileActivityListModel : public ActivityListModel
+{
+ Q_OBJECT
+
+public:
+ explicit FileActivityListModel(QObject *parent = nullptr);
+
+public slots:
+ void load(AccountState *accountState, const QString &fileId);
+
+protected:
+ void startFetchJob() override;
+
+private:
+ QString _fileId;
+};
+}
diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp
index cda9b0cb27f6..decbb927b52c 100644
--- a/src/gui/folder.cpp
+++ b/src/gui/folder.cpp
@@ -28,7 +28,7 @@
#include "clientproxy.h"
#include "syncengine.h"
#include "syncrunfilelog.h"
-#include "socketapi.h"
+#include "socketapi/socketapi.h"
#include "theme.h"
#include "filesystem.h"
#include "localdiscoverytracker.h"
@@ -353,7 +353,7 @@ void Folder::slotRunEtagJob()
// The _requestEtagJob is auto deleting itself on finish. Our guard pointer _requestEtagJob will then be null.
}
-void Folder::etagRetrieved(const QString &etag, const QDateTime &tp)
+void Folder::etagRetrieved(const QByteArray &etag, const QDateTime &tp)
{
// re-enable sync if it was disabled because network was down
FolderMan::instance()->setSyncEnabled(true);
@@ -367,7 +367,7 @@ void Folder::etagRetrieved(const QString &etag, const QDateTime &tp)
_accountState->tagLastSuccessfullETagRequest(tp);
}
-void Folder::etagRetrievedFromSyncEngine(const QString &etag, const QDateTime &time)
+void Folder::etagRetrievedFromSyncEngine(const QByteArray &etag, const QDateTime &time)
{
qCInfo(lcFolder) << "Root etag from during sync:" << etag;
accountState()->tagLastSuccessfullETagRequest(time);
@@ -669,8 +669,10 @@ void Folder::setVirtualFilesEnabled(bool enabled)
_definition.virtualFilesMode = newMode;
startVfs();
- if (newMode != Vfs::Off)
+ if (newMode != Vfs::Off) {
_saveInFoldersWithPlaceholders = true;
+ switchToVirtualFiles();
+ }
saveToSettings();
}
}
@@ -686,6 +688,11 @@ void Folder::setRootPinState(PinState state)
slotNextSyncFullLocalDiscovery();
}
+void Folder::switchToVirtualFiles()
+{
+ SyncEngine::switchToVirtualFiles(path(), _journal, *_vfs);
+}
+
bool Folder::supportsSelectiveSync() const
{
return !virtualFilesEnabled() && !isVfsOnOffSwitchPending();
@@ -874,42 +881,15 @@ void Folder::setSyncOptions()
opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
opt._moveFilesToTrash = cfgFile.moveToTrash();
opt._vfs = _vfs;
+ opt._parallelNetworkJobs = _accountState->account()->isHttp2Supported() ? 20 : 6;
- QByteArray chunkSizeEnv = qgetenv("OWNCLOUD_CHUNK_SIZE");
- if (!chunkSizeEnv.isEmpty()) {
- opt._initialChunkSize = chunkSizeEnv.toUInt();
- } else {
- opt._initialChunkSize = cfgFile.chunkSize();
- }
- QByteArray minChunkSizeEnv = qgetenv("OWNCLOUD_MIN_CHUNK_SIZE");
- if (!minChunkSizeEnv.isEmpty()) {
- opt._minChunkSize = minChunkSizeEnv.toUInt();
- } else {
- opt._minChunkSize = cfgFile.minChunkSize();
- }
- QByteArray maxChunkSizeEnv = qgetenv("OWNCLOUD_MAX_CHUNK_SIZE");
- if (!maxChunkSizeEnv.isEmpty()) {
- opt._maxChunkSize = maxChunkSizeEnv.toUInt();
- } else {
- opt._maxChunkSize = cfgFile.maxChunkSize();
- }
-
- int maxParallel = qgetenv("OWNCLOUD_MAX_PARALLEL").toUInt();
- opt._parallelNetworkJobs = maxParallel ? maxParallel : _accountState->account()->isHttp2Supported() ? 20 : 6;
-
- // Previously min/max chunk size values didn't exist, so users might
- // have setups where the chunk size exceeds the new min/max default
- // values. To cope with this, adjust min/max to always include the
- // initial chunk size value.
- opt._minChunkSize = qMin(opt._minChunkSize, opt._initialChunkSize);
- opt._maxChunkSize = qMax(opt._maxChunkSize, opt._initialChunkSize);
+ opt._initialChunkSize = cfgFile.chunkSize();
+ opt._minChunkSize = cfgFile.minChunkSize();
+ opt._maxChunkSize = cfgFile.maxChunkSize();
+ opt._targetChunkUploadDuration = cfgFile.targetChunkUploadDuration();
- QByteArray targetChunkUploadDurationEnv = qgetenv("OWNCLOUD_TARGET_CHUNK_UPLOAD_DURATION");
- if (!targetChunkUploadDurationEnv.isEmpty()) {
- opt._targetChunkUploadDuration = std::chrono::milliseconds(targetChunkUploadDurationEnv.toUInt());
- } else {
- opt._targetChunkUploadDuration = cfgFile.targetChunkUploadDuration();
- }
+ opt.fillFromEnvironmentVariables();
+ opt.verifyChunkSizes();
_engine->setSyncOptions(opt);
}
@@ -1288,6 +1268,11 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, std::functio
msgBox->open();
}
+QString Folder::fileFromLocalPath(const QString &localPath) const
+{
+ return localPath.mid(cleanPath().length() + 1);
+}
+
void FolderDefinition::save(QSettings &settings, const FolderDefinition &folder)
{
settings.setValue(QLatin1String("localPath"), folder.localPath);
@@ -1381,4 +1366,5 @@ QString FolderDefinition::defaultJournalPath(AccountPtr account)
return SyncJournalDb::makeDbName(localPath, account->url(), targetPath, account->credentials()->user());
}
+
} // namespace OCC
diff --git a/src/gui/folder.h b/src/gui/folder.h
index 809ca85e7960..3bb96b2da487 100644
--- a/src/gui/folder.h
+++ b/src/gui/folder.h
@@ -117,7 +117,7 @@ class Folder : public QObject
*/
Folder(const FolderDefinition &definition, AccountState *accountState, std::unique_ptr vfs, QObject *parent = nullptr);
- ~Folder();
+ ~Folder() override;
using Map = QMap;
using MapIterator = QMapIterator;
@@ -287,9 +287,13 @@ class Folder : public QObject
bool isVfsOnOffSwitchPending() const { return _vfsOnOffPending; }
void setVfsOnOffSwitchPending(bool pending) { _vfsOnOffPending = pending; }
+ void switchToVirtualFiles();
+
/** Whether this folder should show selective sync ui */
bool supportsSelectiveSync() const;
+ QString fileFromLocalPath(const QString &localPath) const;
+
signals:
void syncStateChange();
void syncStarted();
@@ -376,8 +380,8 @@ private slots:
void slotItemCompleted(const SyncFileItemPtr &);
void slotRunEtagJob();
- void etagRetrieved(const QString &, const QDateTime &tp);
- void etagRetrievedFromSyncEngine(const QString &, const QDateTime &time);
+ void etagRetrieved(const QByteArray &, const QDateTime &tp);
+ void etagRetrievedFromSyncEngine(const QByteArray &, const QDateTime &time);
void slotEmitFinishedDelayed();
@@ -447,7 +451,7 @@ private slots:
SyncResult _syncResult;
QScopedPointer _engine;
QPointer _requestEtagJob;
- QString _lastEtag;
+ QByteArray _lastEtag;
QElapsedTimer _timeSinceLastSyncDone;
QElapsedTimer _timeSinceLastSyncStart;
QElapsedTimer _timeSinceLastFullLocalDiscovery;
diff --git a/src/gui/foldercreationdialog.h b/src/gui/foldercreationdialog.h
index 4797b5f932cd..3786b9f51018 100644
--- a/src/gui/foldercreationdialog.h
+++ b/src/gui/foldercreationdialog.h
@@ -29,7 +29,7 @@ class FolderCreationDialog : public QDialog
public:
explicit FolderCreationDialog(const QString &destination, QWidget *parent = nullptr);
- ~FolderCreationDialog();
+ ~FolderCreationDialog() override;
private slots:
void accept() override;
diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp
index 9b0f297e95cc..73ad0c5535ea 100644
--- a/src/gui/folderman.cpp
+++ b/src/gui/folderman.cpp
@@ -17,7 +17,7 @@
#include "folder.h"
#include "syncresult.h"
#include "theme.h"
-#include "socketapi.h"
+#include "socketapi/socketapi.h"
#include "account.h"
#include "accountstate.h"
#include "accountmanager.h"
@@ -292,6 +292,11 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account,
SyncJournalDb::maybeMigrateDb(folderDefinition.localPath, folderDefinition.absoluteJournalPath());
}
+ const auto switchToVfs = isSwitchToVfsNeeded(folderDefinition);
+ if (switchToVfs) {
+ folderDefinition.virtualFilesMode = bestAvailableVfsMode();
+ }
+
auto vfs = createVfsFromPlugin(folderDefinition.virtualFilesMode);
if (!vfs) {
// TODO: Must do better error handling
@@ -300,6 +305,9 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account,
Folder *f = addFolderInternal(std::move(folderDefinition), account.data(), std::move(vfs));
if (f) {
+ if (switchToVfs) {
+ f->switchToVirtualFiles();
+ }
// Migrate the old "usePlaceholders" setting to the root folder pin state
if (settings.value(QLatin1String(versionC), 1).toInt() == 1
&& settings.value(QLatin1String("usePlaceholders"), false).toBool()) {
@@ -837,6 +845,19 @@ bool FolderMan::pushNotificationsFilesReady(Account *account)
return pushFilesAvailable && pushNotifications && pushNotifications->isReady();
}
+bool FolderMan::isSwitchToVfsNeeded(const FolderDefinition &folderDefinition) const
+{
+ auto result = false;
+ if (ENFORCE_VIRTUAL_FILES_SYNC_FOLDER &&
+ folderDefinition.virtualFilesMode != bestAvailableVfsMode() &&
+ folderDefinition.virtualFilesMode == Vfs::Off &&
+ OCC::Theme::instance()->showVirtualFilesOption()) {
+ result = true;
+ }
+
+ return result;
+}
+
void FolderMan::slotEtagPollTimerTimeout()
{
qCInfo(lcFolderMan) << "Etag poll timer timeout";
diff --git a/src/gui/folderman.h b/src/gui/folderman.h
index 815c1288f82d..5a6c234e7d71 100644
--- a/src/gui/folderman.h
+++ b/src/gui/folderman.h
@@ -62,7 +62,7 @@ class FolderMan : public QObject
{
Q_OBJECT
public:
- ~FolderMan();
+ ~FolderMan() override;
static FolderMan *instance();
int setupFolders();
@@ -324,6 +324,8 @@ private slots:
bool pushNotificationsFilesReady(Account *account);
+ bool isSwitchToVfsNeeded(const FolderDefinition &folderDefinition) const;
+
QSet _disabledFolders;
Folder::Map _folderMap;
QString _folderConfigPath;
diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp
index 3ffc048497c6..51bbe4f74840 100644
--- a/src/gui/folderstatusmodel.cpp
+++ b/src/gui/folderstatusmodel.cpp
@@ -907,7 +907,7 @@ void FolderStatusModel::slotApplySelectiveSync()
// The folders that were undecided or blacklisted and that are now checked should go on the white list.
// The user confirmed them already just now.
- QStringList toAddToWhiteList = ((oldBlackListSet + folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok).toSet()) - blackListSet).toList();
+ QStringList toAddToWhiteList = ((oldBlackListSet + folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok).toSet()) - blackListSet).values();
if (!toAddToWhiteList.isEmpty()) {
auto whiteList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, &ok);
diff --git a/src/gui/folderstatusmodel.h b/src/gui/folderstatusmodel.h
index 39d937f09c6e..896a19550bde 100644
--- a/src/gui/folderstatusmodel.h
+++ b/src/gui/folderstatusmodel.h
@@ -42,7 +42,7 @@ class FolderStatusModel : public QAbstractItemModel
enum {FileIdRole = Qt::UserRole+1};
FolderStatusModel(QObject *parent = nullptr);
- ~FolderStatusModel();
+ ~FolderStatusModel() override;
void setAccountState(const AccountState *accountState);
Qt::ItemFlags flags(const QModelIndex &) const override;
diff --git a/src/gui/folderwatcher.h b/src/gui/folderwatcher.h
index c98db8f68816..9972dd50f0ff 100644
--- a/src/gui/folderwatcher.h
+++ b/src/gui/folderwatcher.h
@@ -53,7 +53,7 @@ class FolderWatcher : public QObject
public:
// Construct, connect signals, call init()
explicit FolderWatcher(Folder *folder = nullptr);
- virtual ~FolderWatcher();
+ ~FolderWatcher() override;
/**
* @param root Path of the root of the folder
diff --git a/src/gui/folderwatcher_linux.h b/src/gui/folderwatcher_linux.h
index 277736b40b0d..620e037ed94e 100644
--- a/src/gui/folderwatcher_linux.h
+++ b/src/gui/folderwatcher_linux.h
@@ -37,7 +37,7 @@ class FolderWatcherPrivate : public QObject
public:
FolderWatcherPrivate() = default;
FolderWatcherPrivate(FolderWatcher *p, const QString &path);
- ~FolderWatcherPrivate();
+ ~FolderWatcherPrivate() override;
int testWatchCount() const { return _pathToWatch.size(); }
diff --git a/src/gui/folderwizard.cpp b/src/gui/folderwizard.cpp
index b55cb58e961b..b240d72355fa 100644
--- a/src/gui/folderwizard.cpp
+++ b/src/gui/folderwizard.cpp
@@ -201,21 +201,19 @@ void FolderWizardRemotePath::slotCreateRemoteFolder(const QString &folder)
auto *job = new MkColJob(_account, fullPath, this);
/* check the owncloud configuration file and query the ownCloud */
- connect(job, static_cast(&MkColJob::finished),
+ connect(job, &MkColJob::finishedWithoutError,
this, &FolderWizardRemotePath::slotCreateRemoteFolderFinished);
connect(job, &AbstractNetworkJob::networkError, this, &FolderWizardRemotePath::slotHandleMkdirNetworkError);
job->start();
}
-void FolderWizardRemotePath::slotCreateRemoteFolderFinished(QNetworkReply::NetworkError error)
+void FolderWizardRemotePath::slotCreateRemoteFolderFinished()
{
- if (error == QNetworkReply::NoError) {
- qCDebug(lcWizard) << "webdav mkdir request finished";
- showWarn(tr("Folder was successfully created on %1.").arg(Theme::instance()->appNameGUI()));
- slotRefreshFolders();
- _ui.folderEntry->setText(static_cast(sender())->path());
- slotLsColFolderEntry();
- }
+ qCDebug(lcWizard) << "webdav mkdir request finished";
+ showWarn(tr("Folder was successfully created on %1.").arg(Theme::instance()->appNameGUI()));
+ slotRefreshFolders();
+ _ui.folderEntry->setText(static_cast(sender())->path());
+ slotLsColFolderEntry();
}
void FolderWizardRemotePath::slotHandleMkdirNetworkError(QNetworkReply *reply)
@@ -547,6 +545,11 @@ void FolderWizardSelectiveSync::initializePage()
_virtualFilesCheckBox->setChecked(bestAvailableVfsMode() == Vfs::WindowsCfApi);
_virtualFilesCheckBox->setEnabled(true);
_virtualFilesCheckBox->setText(tr("Use virtual files instead of downloading content immediately %1").arg(bestAvailableVfsMode() == Vfs::WindowsCfApi ? QString() : tr("(experimental)")));
+
+ if (Theme::instance()->enforceVirtualFilesSyncFolder()) {
+ _virtualFilesCheckBox->setChecked(true);
+ _virtualFilesCheckBox->setDisabled(true);
+ }
}
//
}
diff --git a/src/gui/folderwizard.h b/src/gui/folderwizard.h
index 58ffa69c053d..c6e7d48ce69f 100644
--- a/src/gui/folderwizard.h
+++ b/src/gui/folderwizard.h
@@ -53,7 +53,7 @@ class FolderWizardLocalPath : public FormatWarningsWizardPage
Q_OBJECT
public:
explicit FolderWizardLocalPath(const AccountPtr &account);
- ~FolderWizardLocalPath();
+ ~FolderWizardLocalPath() override;
bool isComplete() const override;
void initializePage() override;
@@ -80,7 +80,7 @@ class FolderWizardRemotePath : public FormatWarningsWizardPage
Q_OBJECT
public:
explicit FolderWizardRemotePath(const AccountPtr &account);
- ~FolderWizardRemotePath();
+ ~FolderWizardRemotePath() override;
bool isComplete() const override;
@@ -92,7 +92,7 @@ protected slots:
void showWarn(const QString & = QString()) const;
void slotAddRemoteFolder();
void slotCreateRemoteFolder(const QString &);
- void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError error);
+ void slotCreateRemoteFolderFinished();
void slotHandleMkdirNetworkError(QNetworkReply *);
void slotHandleLsColNetworkError(QNetworkReply *);
void slotUpdateDirectories(const QStringList &);
@@ -124,7 +124,7 @@ class FolderWizardSelectiveSync : public QWizardPage
Q_OBJECT
public:
explicit FolderWizardSelectiveSync(const AccountPtr &account);
- ~FolderWizardSelectiveSync();
+ ~FolderWizardSelectiveSync() override;
bool validatePage() override;
@@ -154,7 +154,7 @@ class FolderWizard : public QWizard
};
explicit FolderWizard(AccountPtr account, QWidget *parent = nullptr);
- ~FolderWizard();
+ ~FolderWizard() override;
bool eventFilter(QObject *watched, QEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp
index 0f4c21f5286c..058bdf1d6699 100644
--- a/src/gui/generalsettings.cpp
+++ b/src/gui/generalsettings.cpp
@@ -21,6 +21,7 @@
#include "configfile.h"
#include "owncloudsetupwizard.h"
#include "accountmanager.h"
+#include "guiutility.h"
#if defined(BUILD_UPDATER)
#include "updater/updater.h"
@@ -275,8 +276,13 @@ void GeneralSettings::slotUpdateInfo()
connect(_ui->updateButton, &QAbstractButton::clicked, this, &GeneralSettings::slotUpdateCheckNow, Qt::UniqueConnection);
connect(_ui->autoCheckForUpdatesCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleAutoUpdateCheck);
- QString status = ocupdater->statusString();
+ QString status = ocupdater->statusString(OCUpdater::UpdateStatusStringFormat::Html);
Theme::replaceLinkColorStringBackgroundAware(status);
+
+ _ui->updateStateLabel->setOpenExternalLinks(false);
+ connect(_ui->updateStateLabel, &QLabel::linkActivated, this, [](const QString &link) {
+ Utility::openBrowser(QUrl(link));
+ });
_ui->updateStateLabel->setText(status);
_ui->restartButton->setVisible(ocupdater->downloadState() == OCUpdater::DownloadComplete);
diff --git a/src/gui/generalsettings.h b/src/gui/generalsettings.h
index 9012b5eca8d2..06675c8cce49 100644
--- a/src/gui/generalsettings.h
+++ b/src/gui/generalsettings.h
@@ -36,7 +36,7 @@ class GeneralSettings : public QWidget
public:
explicit GeneralSettings(QWidget *parent = nullptr);
- ~GeneralSettings();
+ ~GeneralSettings() override;
QSize sizeHint() const override;
public slots:
diff --git a/src/gui/iconutils.cpp b/src/gui/iconutils.cpp
new file mode 100644
index 000000000000..40ad051ce15a
--- /dev/null
+++ b/src/gui/iconutils.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) by Oleksandr Zolotov
+ *
+ * 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.
+ */
+
+#include "iconutils.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace {
+QString findSvgFilePath(const QString &fileName, const QStringList &possibleColors)
+{
+ QString result;
+ result = QString{OCC::Theme::themePrefix} + fileName;
+ if (QFile::exists(result)) {
+ return result;
+ } else {
+ for (const auto &color : possibleColors) {
+ result = QString{OCC::Theme::themePrefix} + color + QStringLiteral("/") + fileName;
+
+ if (QFile::exists(result)) {
+ return result;
+ }
+ }
+ result.clear();
+ }
+
+ return result;
+}
+}
+
+namespace OCC {
+namespace Ui {
+namespace IconUtils {
+Q_LOGGING_CATEGORY(lcIconUtils, "nextcloud.gui.iconutils", QtInfoMsg)
+QPixmap pixmapForBackground(const QString &fileName, const QColor &backgroundColor)
+{
+ Q_ASSERT(!fileName.isEmpty());
+
+ const auto pixmapColor = backgroundColor.isValid() && !Theme::isDarkColor(backgroundColor)
+ ? QColorConstants::Svg::black
+ : QColorConstants::Svg::white;
+ ;
+ return createSvgPixmapWithCustomColorCached(fileName, pixmapColor);
+}
+
+QImage createSvgImageWithCustomColor(const QString &fileName, const QColor &customColor, QSize *originalSize, const QSize &requestedSize)
+{
+ Q_ASSERT(!fileName.isEmpty());
+ Q_ASSERT(customColor.isValid());
+
+ QImage result{};
+
+ if (fileName.isEmpty() || !customColor.isValid()) {
+ qWarning(lcIconUtils) << "invalid fileName or customColor";
+ return result;
+ }
+
+ // some icons are present in white or black only, so, we need to check both when needed
+ const auto iconBaseColors = QStringList{QStringLiteral("black"), QStringLiteral("white")};
+
+ // check if there is an existing image matching the custom color
+ {
+ const auto customColorName = [&customColor]() {
+ auto result = customColor.name();
+ if (result.startsWith(QStringLiteral("#"))) {
+ if (result == QStringLiteral("#000000")) {
+ result = QStringLiteral("black");
+ }
+ if (result == QStringLiteral("#ffffff")) {
+ result = QStringLiteral("white");
+ }
+ }
+ return result;
+ }();
+
+ if (iconBaseColors.contains(customColorName)) {
+ result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
+ if (!result.isNull()) {
+ return result;
+ }
+ }
+ }
+
+ // find the first matching svg file
+ const auto sourceSvg = findSvgFilePath(fileName, iconBaseColors);
+
+ Q_ASSERT(!sourceSvg.isEmpty());
+ if (sourceSvg.isEmpty()) {
+ qWarning(lcIconUtils) << "Failed to find base SVG file for" << fileName;
+ return result;
+ }
+
+ result = drawSvgWithCustomFillColor(sourceSvg, customColor, originalSize, requestedSize);
+
+ Q_ASSERT(!result.isNull());
+ if (result.isNull()) {
+ qWarning(lcIconUtils) << "Failed to load pixmap for" << fileName;
+ }
+
+ return result;
+}
+
+QPixmap createSvgPixmapWithCustomColorCached(const QString &fileName, const QColor &customColor, QSize *originalSize, const QSize &requestedSize)
+{
+ QPixmap cachedPixmap;
+
+ const auto customColorName = customColor.name();
+
+ const QString cacheKey = fileName + QStringLiteral(",") + customColorName;
+
+ // check for existing QPixmap in cache
+ if (QPixmapCache::find(cacheKey, &cachedPixmap)) {
+ if (originalSize) {
+ *originalSize = {};
+ }
+ return cachedPixmap;
+ }
+
+ cachedPixmap = QPixmap::fromImage(createSvgImageWithCustomColor(fileName, customColor, originalSize, requestedSize));
+
+ if (!cachedPixmap.isNull()) {
+ QPixmapCache::insert(cacheKey, cachedPixmap);
+ }
+
+ return cachedPixmap;
+}
+
+QImage drawSvgWithCustomFillColor(
+ const QString &sourceSvgPath, const QColor &fillColor, QSize *originalSize, const QSize &requestedSize)
+{
+ QSvgRenderer svgRenderer;
+
+ if (!svgRenderer.load(sourceSvgPath)) {
+ qCWarning(lcIconUtils) << "Could no load initial SVG image";
+ return {};
+ }
+
+ const auto reqSize = requestedSize.isValid() ? requestedSize : svgRenderer.defaultSize();
+
+ if (originalSize) {
+ *originalSize = svgRenderer.defaultSize();
+ }
+
+ // render source image
+ QImage svgImage(reqSize, QImage::Format_ARGB32);
+ {
+ QPainter svgImagePainter(&svgImage);
+ svgImage.fill(Qt::GlobalColor::transparent);
+ svgRenderer.render(&svgImagePainter);
+ }
+
+ // draw target image with custom fillColor
+ QImage image(reqSize, QImage::Format_ARGB32);
+ image.fill(QColor(fillColor));
+ {
+ QPainter imagePainter(&image);
+ imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ imagePainter.drawImage(0, 0, svgImage);
+ }
+
+ return image;
+}
+}
+}
+}
diff --git a/src/gui/iconutils.h b/src/gui/iconutils.h
new file mode 100644
index 000000000000..af5930cb5acb
--- /dev/null
+++ b/src/gui/iconutils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) by Oleksandr Zolotov
+ *
+ * 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.
+ */
+
+#ifndef ICONUTILS_H
+#define ICONUTILS_H
+
+#include
+#include
+
+namespace OCC {
+namespace Ui {
+namespace IconUtils {
+QPixmap pixmapForBackground(const QString &fileName, const QColor &backgroundColor);
+QImage createSvgImageWithCustomColor(const QString &fileName, const QColor &customColor, QSize *originalSize = nullptr, const QSize &requestedSize = {});
+QPixmap createSvgPixmapWithCustomColorCached(const QString &fileName, const QColor &customColor, QSize *originalSize = nullptr, const QSize &requestedSize = {});
+QImage drawSvgWithCustomFillColor(const QString &sourceSvgPath, const QColor &fillColor, QSize *originalSize = nullptr, const QSize &requestedSize = {});
+}
+}
+}
+#endif // ICONUTILS_H
diff --git a/src/gui/ignorelisteditor.h b/src/gui/ignorelisteditor.h
index 39c38d74d457..e425fc784925 100644
--- a/src/gui/ignorelisteditor.h
+++ b/src/gui/ignorelisteditor.h
@@ -36,7 +36,7 @@ class IgnoreListEditor : public QDialog
public:
IgnoreListEditor(QWidget *parent = nullptr);
- ~IgnoreListEditor();
+ ~IgnoreListEditor() override;
bool ignoreHiddenFiles();
diff --git a/src/gui/ignorelisttablewidget.h b/src/gui/ignorelisttablewidget.h
index 3bded0462a0c..39d43fde9824 100644
--- a/src/gui/ignorelisttablewidget.h
+++ b/src/gui/ignorelisttablewidget.h
@@ -16,7 +16,7 @@ class IgnoreListTableWidget : public QWidget
public:
IgnoreListTableWidget(QWidget *parent = nullptr);
- ~IgnoreListTableWidget();
+ ~IgnoreListTableWidget() override;
void readIgnoreFile(const QString &file, bool readOnly = false);
int addPattern(const QString &pattern, bool deletable, bool readOnly);
diff --git a/src/gui/invalidfilenamedialog.cpp b/src/gui/invalidfilenamedialog.cpp
new file mode 100644
index 000000000000..8b318fed3a90
--- /dev/null
+++ b/src/gui/invalidfilenamedialog.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#include "invalidfilenamedialog.h"
+#include "accountfwd.h"
+#include "common/syncjournalfilerecord.h"
+#include "propagateremotemove.h"
+#include "ui_invalidfilenamedialog.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace {
+constexpr std::array illegalCharacters({ '\\', '/', ':', '?', '*', '\"', '<', '>', '|' });
+
+QVector getIllegalCharsFromString(const QString &string)
+{
+ QVector result;
+ for (const auto &character : string) {
+ if (std::find(illegalCharacters.begin(), illegalCharacters.end(), character)
+ != illegalCharacters.end()) {
+ result.push_back(character);
+ }
+ }
+ return result;
+}
+
+QString illegalCharacterListToString(const QVector &illegalCharacters)
+{
+ QString illegalCharactersString;
+ if (illegalCharacters.size() > 0) {
+ illegalCharactersString += illegalCharacters[0];
+ }
+
+ for (int i = 1; i < illegalCharacters.count(); ++i) {
+ if (illegalCharactersString.contains(illegalCharacters[i])) {
+ continue;
+ }
+ illegalCharactersString += " " + illegalCharacters[i];
+ }
+ return illegalCharactersString;
+}
+}
+
+namespace OCC {
+
+InvalidFilenameDialog::InvalidFilenameDialog(AccountPtr account, Folder *folder, QString filePath, QWidget *parent)
+ : QDialog(parent)
+ , _ui(new Ui::InvalidFilenameDialog)
+ , _account(account)
+ , _folder(folder)
+ , _filePath(std::move(filePath))
+{
+ Q_ASSERT(_account);
+ Q_ASSERT(_folder);
+
+ const auto filePathFileInfo = QFileInfo(_filePath);
+ _relativeFilePath = filePathFileInfo.path() + QStringLiteral("/");
+ _relativeFilePath = _relativeFilePath.replace(folder->path(), QStringLiteral(""));
+ _relativeFilePath = _relativeFilePath.isEmpty() ? QStringLiteral("") : _relativeFilePath + QStringLiteral("/");
+
+ _originalFileName = _relativeFilePath + filePathFileInfo.fileName();
+
+ _ui->setupUi(this);
+ _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ _ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Rename file"));
+
+ _ui->descriptionLabel->setText(tr("The file %1 could not be synced because the name contains characters which are not allowed on this system.").arg(_originalFileName));
+ _ui->explanationLabel->setText(tr("The following characters are not allowed on the system: * \" | & ? , ; : \\ / ~ < >"));
+ _ui->filenameLineEdit->setText(filePathFileInfo.fileName());
+
+ connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ connect(_ui->filenameLineEdit, &QLineEdit::textChanged, this,
+ &InvalidFilenameDialog::onFilenameLineEditTextChanged);
+
+ checkIfAllowedToRename();
+}
+
+InvalidFilenameDialog::~InvalidFilenameDialog() = default;
+
+void InvalidFilenameDialog::checkIfAllowedToRename()
+{
+ const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(_folder->remotePath() + _originalFileName));
+ propfindJob->setProperties({ "http://owncloud.org/ns:permissions" });
+ connect(propfindJob, &PropfindJob::result, this, &InvalidFilenameDialog::onPropfindPermissionSuccess);
+ propfindJob->start();
+}
+
+void InvalidFilenameDialog::onPropfindPermissionSuccess(const QVariantMap &values)
+{
+ if (!values.contains("permissions")) {
+ return;
+ }
+ const auto remotePermissions = RemotePermissions::fromServerString(values["permissions"].toString());
+ if (!remotePermissions.hasPermission(remotePermissions.CanRename)
+ || !remotePermissions.hasPermission(remotePermissions.CanMove)) {
+ _ui->errorLabel->setText(
+ tr("You don't have the permission to rename this file. Please ask the author of the file to rename it."));
+ _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ _ui->filenameLineEdit->setEnabled(false);
+ }
+}
+
+void InvalidFilenameDialog::accept()
+{
+ _newFilename = _relativeFilePath + _ui->filenameLineEdit->text().trimmed();
+ const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(_folder->remotePath() + _newFilename));
+ connect(propfindJob, &PropfindJob::result, this, &InvalidFilenameDialog::onRemoteFileAlreadyExists);
+ connect(propfindJob, &PropfindJob::finishedWithError, this, &InvalidFilenameDialog::onRemoteFileDoesNotExist);
+ propfindJob->start();
+}
+
+void InvalidFilenameDialog::onFilenameLineEditTextChanged(const QString &text)
+{
+ const auto isNewFileNameDifferent = text != _originalFileName;
+ const auto illegalContainedCharacters = getIllegalCharsFromString(text);
+ const auto containsIllegalChars = !illegalContainedCharacters.empty() || text.endsWith(QLatin1Char('.'));
+ const auto isTextValid = isNewFileNameDifferent && !containsIllegalChars;
+
+ if (isTextValid) {
+ _ui->errorLabel->setText("");
+ } else {
+ _ui->errorLabel->setText(tr("Filename contains illegal characters: %1")
+ .arg(illegalCharacterListToString(illegalContainedCharacters)));
+ }
+
+ _ui->buttonBox->button(QDialogButtonBox::Ok)
+ ->setEnabled(isTextValid);
+}
+
+void InvalidFilenameDialog::onMoveJobFinished()
+{
+ const auto job = qobject_cast(sender());
+ const auto error = job->reply()->error();
+
+ if (error != QNetworkReply::NoError) {
+ _ui->errorLabel->setText(tr("Could not rename file. Please make sure you are connected to the server."));
+ return;
+ }
+
+ QDialog::accept();
+}
+
+void InvalidFilenameDialog::onRemoteFileAlreadyExists(const QVariantMap &values)
+{
+ Q_UNUSED(values);
+
+ _ui->errorLabel->setText(tr("Cannot rename file because a file with the same name does already exist on the server. Please pick another name."));
+ _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+}
+
+void InvalidFilenameDialog::onRemoteFileDoesNotExist(QNetworkReply *reply)
+{
+ Q_UNUSED(reply);
+
+ // File does not exist. We can rename it.
+ const auto remoteSource = QDir::cleanPath(_folder->remotePath() + _originalFileName);
+ const auto remoteDestionation = QDir::cleanPath(_account->davUrl().path() + _folder->remotePath() + _newFilename);
+ const auto moveJob = new MoveJob(_account, remoteSource, remoteDestionation, this);
+ connect(moveJob, &MoveJob::finishedSignal, this, &InvalidFilenameDialog::onMoveJobFinished);
+ moveJob->start();
+}
+}
diff --git a/src/gui/invalidfilenamedialog.h b/src/gui/invalidfilenamedialog.h
new file mode 100644
index 000000000000..2b6ff0dedd33
--- /dev/null
+++ b/src/gui/invalidfilenamedialog.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) by Felix Weilbach
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+#include
+
+namespace OCC {
+
+class Folder;
+
+namespace Ui {
+ class InvalidFilenameDialog;
+}
+
+
+class InvalidFilenameDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit InvalidFilenameDialog(AccountPtr account, Folder *folder, QString filePath, QWidget *parent = nullptr);
+
+ ~InvalidFilenameDialog() override;
+
+ void accept() override;
+
+private:
+ std::unique_ptr _ui;
+
+ AccountPtr _account;
+ Folder *_folder;
+ QString _filePath;
+ QString _relativeFilePath;
+ QString _originalFileName;
+ QString _newFilename;
+
+ void onFilenameLineEditTextChanged(const QString &text);
+ void onMoveJobFinished();
+ void onRemoteFileAlreadyExists(const QVariantMap &values);
+ void onRemoteFileDoesNotExist(QNetworkReply *reply);
+ void checkIfAllowedToRename();
+ void onPropfindPermissionSuccess(const QVariantMap &values);
+};
+}
diff --git a/src/gui/invalidfilenamedialog.ui b/src/gui/invalidfilenamedialog.ui
new file mode 100644
index 000000000000..68008709deb1
--- /dev/null
+++ b/src/gui/invalidfilenamedialog.ui
@@ -0,0 +1,121 @@
+
+
+ OCC::InvalidFilenameDialog
+
+
+
+ 0
+ 0
+ 411
+ 192
+
+
+
+ Invalid filename
+
+
+
+ QLayout::SetDefaultConstraint
+
+ -
+
+
+ The file could not be synced because it contains characters which are not allowed on this system.
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ false
+
+
+
+ -
+
+
+ Error
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ false
+
+
+
+ -
+
+
+ Please enter a new name for the file:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ false
+
+
+
+ -
+
+
+ New filename
+
+
+
+ -
+
+
+
+
+
+
+
+ 255
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 255
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
diff --git a/src/gui/legalnotice.h b/src/gui/legalnotice.h
index ee0cb9d4ea6f..031ca674084d 100644
--- a/src/gui/legalnotice.h
+++ b/src/gui/legalnotice.h
@@ -35,7 +35,7 @@ class LegalNotice : public QDialog
public:
explicit LegalNotice(QDialog *parent = nullptr);
- ~LegalNotice();
+ ~LegalNotice() override;
protected:
void changeEvent(QEvent *) override;
diff --git a/src/gui/logbrowser.h b/src/gui/logbrowser.h
index c49e26b73604..b1bb547ad893 100644
--- a/src/gui/logbrowser.h
+++ b/src/gui/logbrowser.h
@@ -38,7 +38,7 @@ class LogBrowser : public QDialog
Q_OBJECT
public:
explicit LogBrowser(QWidget *parent = nullptr);
- ~LogBrowser();
+ ~LogBrowser() override;
protected:
void closeEvent(QCloseEvent *) override;
diff --git a/src/gui/main.cpp b/src/gui/main.cpp
index a7a47e16e71e..bf78b4c076db 100644
--- a/src/gui/main.cpp
+++ b/src/gui/main.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
#ifdef Q_OS_UNIX
#include
@@ -23,9 +24,14 @@
#endif
#include "application.h"
+#include "fileactivitylistmodel.h"
#include "theme.h"
#include "common/utility.h"
#include "cocoainitializer.h"
+#include "userstatusselectormodel.h"
+#include "emojimodel.h"
+#include "tray/syncstatussummary.h"
+#include "tray/unifiedsearchresultslistmodel.h"
#if defined(BUILD_UPDATER)
#include "updater/updater.h"
@@ -36,6 +42,7 @@
#include
#include
#include
+#include
using namespace OCC;
@@ -51,9 +58,27 @@ void warnSystray()
int main(int argc, char **argv)
{
+#ifdef Q_OS_WIN
+ SetDllDirectory(L"");
+#endif
Q_INIT_RESOURCE(resources);
Q_INIT_RESOURCE(theme);
+ qmlRegisterType("com.nextcloud.desktopclient", 1, 0, "SyncStatusSummary");
+ qmlRegisterType("com.nextcloud.desktopclient", 1, 0, "EmojiModel");
+ qmlRegisterType("com.nextcloud.desktopclient", 1, 0, "UserStatusSelectorModel");
+ qmlRegisterType("com.nextcloud.desktopclient", 1, 0, "ActivityListModel");
+ qmlRegisterType("com.nextcloud.desktopclient", 1, 0, "FileActivityListModel");
+ qmlRegisterUncreatableType(
+ "com.nextcloud.desktopclient", 1, 0, "UnifiedSearchResultsListModel", "UnifiedSearchResultsListModel");
+ qRegisterMetaType("UnifiedSearchResultsListModel*");
+
+ qmlRegisterUncreatableType("com.nextcloud.desktopclient", 1, 0, "UserStatus", "Access to Status enum");
+
+ qRegisterMetaTypeStreamOperators();
+ qRegisterMetaType("UserStatus");
+
+
// Work around a bug in KDE's qqc2-desktop-style which breaks
// buttons with icons not based on a name, by forcing a style name
// the platformtheme plugin won't try to force qqc2-desktops-style
@@ -101,6 +126,10 @@ int main(int argc, char **argv)
}
#endif
+ auto surfaceFormat = QSurfaceFormat::defaultFormat();
+ surfaceFormat.setOption(QSurfaceFormat::ResetNotification);
+ QSurfaceFormat::setDefaultFormat(surfaceFormat);
+
// check a environment variable for core dumps
#ifdef Q_OS_UNIX
if (!qEnvironmentVariableIsEmpty("OWNCLOUD_CORE_DUMP")) {
diff --git a/src/gui/networksettings.h b/src/gui/networksettings.h
index 4fd6db5720a4..97b892731b1b 100644
--- a/src/gui/networksettings.h
+++ b/src/gui/networksettings.h
@@ -34,7 +34,7 @@ class NetworkSettings : public QWidget
public:
explicit NetworkSettings(QWidget *parent = nullptr);
- ~NetworkSettings();
+ ~NetworkSettings() override;
QSize sizeHint() const override;
private slots:
diff --git a/src/gui/notificationconfirmjob.cpp b/src/gui/notificationconfirmjob.cpp
index d9a7a4c344a0..09e147da3a7d 100644
--- a/src/gui/notificationconfirmjob.cpp
+++ b/src/gui/notificationconfirmjob.cpp
@@ -56,10 +56,11 @@ bool NotificationConfirmJob::finished()
const QString replyStr = reply()->readAll();
if (replyStr.contains("")) {
- QRegExp rex("(\\d+)");
- if (replyStr.contains(rex)) {
+ const QRegularExpression rex("(\\d+)");
+ const auto rexMatch = rex.match(replyStr);
+ if (rexMatch.hasMatch()) {
// this is a error message coming back from ocs.
- replyCode = rex.cap(1).toInt();
+ replyCode = rexMatch.captured(1).toInt();
}
}
emit jobFinished(replyStr, replyCode);
diff --git a/src/gui/ocssharejob.cpp b/src/gui/ocssharejob.cpp
index fcbfafe77ae0..900074dbcc3c 100644
--- a/src/gui/ocssharejob.cpp
+++ b/src/gui/ocssharejob.cpp
@@ -118,6 +118,17 @@ void OcsShareJob::setPermissions(const QString &shareId,
start();
}
+void OcsShareJob::setLabel(const QString &shareId, const QString &label)
+{
+ appendPath(shareId);
+ setVerb("PUT");
+
+ addParam(QStringLiteral("label"), label);
+ _value = label;
+
+ start();
+}
+
void OcsShareJob::createLinkShare(const QString &path,
const QString &name,
const QString &password)
diff --git a/src/gui/ocssharejob.h b/src/gui/ocssharejob.h
index 074fa0762186..064706b5c6db 100644
--- a/src/gui/ocssharejob.h
+++ b/src/gui/ocssharejob.h
@@ -96,6 +96,11 @@ class OcsShareJob : public OcsJob
*/
void setPermissions(const QString &shareId,
const Share::Permissions permissions);
+
+ /**
+ * Set share link label
+ */
+ void setLabel(const QString &shareId, const QString &label);
/**
* Create a new link share
diff --git a/src/gui/openfilemanager.cpp b/src/gui/openfilemanager.cpp
index 3754bbd9feab..4a4161434fed 100644
--- a/src/gui/openfilemanager.cpp
+++ b/src/gui/openfilemanager.cpp
@@ -103,7 +103,7 @@ void showInFileManager(const QString &localPath)
return;
#endif
- QString explorer = "explorer.exe "; // FIXME: we trust it's in PATH
+ const QString explorer = "explorer.exe "; // FIXME: we trust it's in PATH
QFileInfo fi(localPath);
// canonicalFilePath returns empty if the file does not exist
@@ -123,7 +123,7 @@ void showInFileManager(const QString &localPath)
// only around the path. Use setNativeArguments to bypass this logic.
p.setNativeArguments(nativeArgs);
#endif
- p.start(explorer);
+ p.start(explorer, QStringList {});
p.waitForFinished(5000);
}
} else if (Utility::isMac()) {
diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp
index 99fe2a998e97..9c86e9cf9eac 100644
--- a/src/gui/owncloudgui.cpp
+++ b/src/gui/owncloudgui.cpp
@@ -640,19 +640,7 @@ void ownCloudGui::slotShowShareDialog(const QString &sharePath, const QString &l
}
}
- // As a first approximation, set the set of permissions that can be granted
- // either to everything (resharing allowed) or nothing (no resharing).
- //
- // The correct value will be found with a propfind from ShareDialog.
- // (we want to show the dialog directly, not wait for the propfind first)
- SharePermissions maxSharingPermissions =
- SharePermissionRead
- | SharePermissionUpdate | SharePermissionCreate | SharePermissionDelete
- | SharePermissionShare;
- if (!resharingAllowed) {
- maxSharingPermissions = {};
- }
-
+ auto maxSharingPermissions = resharingAllowed? SharePermissions(accountState->account()->capabilities().shareDefaultPermissions()) : SharePermissions({});
ShareDialog *w = nullptr;
if (_shareDialogs.contains(localPath) && _shareDialogs[localPath]) {
diff --git a/src/gui/owncloudsetupwizard.cpp b/src/gui/owncloudsetupwizard.cpp
index ce0dd773fb4e..86c4524a8603 100644
--- a/src/gui/owncloudsetupwizard.cpp
+++ b/src/gui/owncloudsetupwizard.cpp
@@ -323,12 +323,29 @@ void OwncloudSetupWizard::slotConnectToOCUrl(const QString &url)
qCInfo(lcWizard) << "Connect to url: " << url;
AbstractCredentials *creds = _ocWizard->getCredentials();
_ocWizard->account()->setCredentials(creds);
- _ocWizard->setField(QLatin1String("OCUrl"), url);
- _ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 …")
- .arg(Theme::instance()->appNameGUI())
- .arg(url));
- testOwnCloudConnect();
+ const auto fetchUserNameJob = new JsonApiJob(_ocWizard->account()->sharedFromThis(), QStringLiteral("/ocs/v1.php/cloud/user"));
+ connect(fetchUserNameJob, &JsonApiJob::jsonReceived, this, [this, url](const QJsonDocument &json, int statusCode) {
+ if (statusCode != 100) {
+ qCWarning(lcWizard) << "Could not fetch username.";
+ }
+
+ sender()->deleteLater();
+
+ const auto objData = json.object().value("ocs").toObject().value("data").toObject();
+ const auto userId = objData.value("id").toString("");
+ const auto displayName = objData.value("display-name").toString("");
+ _ocWizard->account()->setDavUser(userId);
+ _ocWizard->account()->setDavDisplayName(displayName);
+
+ _ocWizard->setField(QLatin1String("OCUrl"), url);
+ _ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 …")
+ .arg(Theme::instance()->appNameGUI())
+ .arg(url));
+
+ testOwnCloudConnect();
+ });
+ fetchUserNameJob->start();
}
void OwncloudSetupWizard::testOwnCloudConnect()
@@ -536,26 +553,28 @@ void OwncloudSetupWizard::createRemoteFolder()
_ocWizard->appendToConfigurationLog(tr("creating folder on Nextcloud: %1").arg(_remoteFolder));
auto *job = new MkColJob(_ocWizard->account(), _remoteFolder, this);
- connect(job, SIGNAL(finished(QNetworkReply::NetworkError)), SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError)));
+ connect(job, &MkColJob::finishedWithError, this, &OwncloudSetupWizard::slotCreateRemoteFolderFinished);
+ connect(job, &MkColJob::finishedWithoutError, this, [this] {
+ _ocWizard->appendToConfigurationLog(tr("Remote folder %1 created successfully.").arg(_remoteFolder));
+ finalizeSetup(true);
+ });
job->start();
}
-void OwncloudSetupWizard::slotCreateRemoteFolderFinished(QNetworkReply::NetworkError error)
+void OwncloudSetupWizard::slotCreateRemoteFolderFinished(QNetworkReply *reply)
{
+ auto error = reply->error();
qCDebug(lcWizard) << "** webdav mkdir request finished " << error;
// disconnect(ownCloudInfo::instance(), SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
// this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError)));
bool success = true;
-
- if (error == QNetworkReply::NoError) {
- _ocWizard->appendToConfigurationLog(tr("Remote folder %1 created successfully.").arg(_remoteFolder));
- } else if (error == 202) {
+ if (error == 202) {
_ocWizard->appendToConfigurationLog(tr("The remote folder %1 already exists. Connecting it for syncing.").arg(_remoteFolder));
} else if (error > 202 && error < 300) {
- _ocWizard->displayError(tr("The folder creation resulted in HTTP error code %1").arg((int)error), false);
+ _ocWizard->displayError(tr("The folder creation resulted in HTTP error code %1").arg(static_cast(error)), false);
- _ocWizard->appendToConfigurationLog(tr("The folder creation resulted in HTTP error code %1").arg((int)error));
+ _ocWizard->appendToConfigurationLog(tr("The folder creation resulted in HTTP error code %1").arg(static_cast(error)));
} else if (error == QNetworkReply::OperationCanceledError) {
_ocWizard->displayError(tr("The remote folder creation failed because the provided credentials "
"are wrong!"
@@ -577,9 +596,6 @@ void OwncloudSetupWizard::slotCreateRemoteFolderFinished(QNetworkReply::NetworkE
void OwncloudSetupWizard::finalizeSetup(bool success)
{
- // enable/disable the finish button.
- _ocWizard->enableFinishOnResultWidget(success);
-
const QString localFolder = _ocWizard->property("localFolder").toString();
if (success) {
if (!(localFolder.isEmpty() || _remoteFolder.isEmpty())) {
@@ -668,6 +684,7 @@ void OwncloudSetupWizard::slotAssistantFinished(int result)
}
// notify others.
+ _ocWizard->done(QWizard::Accepted);
emit ownCloudWizardDone(result);
}
diff --git a/src/gui/owncloudsetupwizard.h b/src/gui/owncloudsetupwizard.h
index 4762de1cd880..d7288ee6c8b7 100644
--- a/src/gui/owncloudsetupwizard.h
+++ b/src/gui/owncloudsetupwizard.h
@@ -65,13 +65,13 @@ private slots:
void slotCreateLocalAndRemoteFolders(const QString &, const QString &);
void slotRemoteFolderExists(QNetworkReply *);
- void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError);
+ void slotCreateRemoteFolderFinished(QNetworkReply *reply);
void slotAssistantFinished(int);
void slotSkipFolderConfiguration();
private:
explicit OwncloudSetupWizard(QObject *parent = nullptr);
- ~OwncloudSetupWizard();
+ ~OwncloudSetupWizard() override;
void startWizard();
void testOwnCloudConnect();
void createRemoteFolder();
diff --git a/src/gui/profilepagewidget.cpp b/src/gui/profilepagewidget.cpp
new file mode 100644
index 000000000000..5bed47d8a5ad
--- /dev/null
+++ b/src/gui/profilepagewidget.cpp
@@ -0,0 +1,46 @@
+#include "profilepagewidget.h"
+#include "guiutility.h"
+#include "ocsprofileconnector.h"
+
+namespace OCC {
+
+ProfilePageMenu::ProfilePageMenu(AccountPtr account, const QString &shareWithUserId, QWidget *parent)
+ : QWidget(parent)
+ , _profileConnector(account)
+{
+ connect(&_profileConnector, &OcsProfileConnector::hovercardFetched, this, &ProfilePageMenu::onHovercardFetched);
+ connect(&_profileConnector, &OcsProfileConnector::iconLoaded, this, &ProfilePageMenu::onIconLoaded);
+ _profileConnector.fetchHovercard(shareWithUserId);
+}
+
+ProfilePageMenu::~ProfilePageMenu() = default;
+
+void ProfilePageMenu::exec(const QPoint &globalPosition)
+{
+ _menu.exec(globalPosition);
+}
+
+void ProfilePageMenu::onHovercardFetched()
+{
+ _menu.clear();
+
+ const auto hovercardActions = _profileConnector.hovercard()._actions;
+ for (const auto &hovercardAction : hovercardActions) {
+ const auto action = _menu.addAction(hovercardAction._icon, hovercardAction._title);
+ const auto link = hovercardAction._link;
+ connect(action, &QAction::triggered, action, [link](bool) { Utility::openBrowser(link); });
+ }
+}
+
+void ProfilePageMenu::onIconLoaded(const std::size_t &hovercardActionIndex)
+{
+ const auto hovercardActions = _profileConnector.hovercard()._actions;
+ const auto menuActions = _menu.actions();
+ if (hovercardActionIndex >= hovercardActions.size()
+ || hovercardActionIndex >= static_cast(menuActions.size())) {
+ return;
+ }
+ const auto menuAction = menuActions[static_cast(hovercardActionIndex)];
+ menuAction->setIcon(hovercardActions[hovercardActionIndex]._icon);
+}
+}
diff --git a/src/gui/profilepagewidget.h b/src/gui/profilepagewidget.h
new file mode 100644
index 000000000000..637dbd460e15
--- /dev/null
+++ b/src/gui/profilepagewidget.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "ocsprofileconnector.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+namespace OCC {
+
+class ProfilePageMenu : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit ProfilePageMenu(AccountPtr account, const QString &shareWithUserId, QWidget *parent = nullptr);
+ ~ProfilePageMenu() override;
+
+ void exec(const QPoint &globalPosition);
+
+private:
+ void onHovercardFetched();
+ void onIconLoaded(const std::size_t &hovercardActionIndex);
+
+ OcsProfileConnector _profileConnector;
+ QMenu _menu;
+};
+}
diff --git a/src/gui/proxyauthdialog.h b/src/gui/proxyauthdialog.h
index 9ce75f691216..63a262b8a4c1 100644
--- a/src/gui/proxyauthdialog.h
+++ b/src/gui/proxyauthdialog.h
@@ -34,7 +34,7 @@ class ProxyAuthDialog : public QDialog
public:
explicit ProxyAuthDialog(QWidget *parent = nullptr);
- ~ProxyAuthDialog();
+ ~ProxyAuthDialog() override;
void setProxyAddress(const QString &address);
diff --git a/src/gui/proxyauthhandler.h b/src/gui/proxyauthhandler.h
index e1a29141115a..06d28a62affe 100644
--- a/src/gui/proxyauthhandler.h
+++ b/src/gui/proxyauthhandler.h
@@ -49,7 +49,7 @@ class ProxyAuthHandler : public QObject
public:
static ProxyAuthHandler *instance();
- virtual ~ProxyAuthHandler();
+ ~ProxyAuthHandler() override;
public slots:
/// Intended for QNetworkAccessManager::proxyAuthenticationRequired()
diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h
index f46208d533a7..0d84a1cb19d3 100644
--- a/src/gui/settingsdialog.h
+++ b/src/gui/settingsdialog.h
@@ -49,7 +49,7 @@ class SettingsDialog : public QDialog
public:
explicit SettingsDialog(ownCloudGui *gui, QWidget *parent = nullptr);
- ~SettingsDialog();
+ ~SettingsDialog() override;
QWidget* currentPage();
diff --git a/src/gui/sharedialog.cpp b/src/gui/sharedialog.cpp
index f8c4b68d88ef..6f5e2837d2eb 100644
--- a/src/gui/sharedialog.cpp
+++ b/src/gui/sharedialog.cpp
@@ -96,8 +96,8 @@ ShareDialog::ShareDialog(QPointer accountState,
QString ocDir(_sharePath);
ocDir.truncate(ocDir.length() - fileName.length());
- ocDir.replace(QRegExp("^/*"), "");
- ocDir.replace(QRegExp("/*$"), "");
+ ocDir.replace(QRegularExpression("^/*"), "");
+ ocDir.replace(QRegularExpression("/*$"), "");
// Laying this out is complex because sharePath
// may be in use or not.
diff --git a/src/gui/sharedialog.h b/src/gui/sharedialog.h
index 96a5f07e0d43..6431cb13194a 100644
--- a/src/gui/sharedialog.h
+++ b/src/gui/sharedialog.h
@@ -51,7 +51,7 @@ class ShareDialog : public QDialog
const QByteArray &numericFileId,
ShareDialogStartPage startPage,
QWidget *parent = nullptr);
- ~ShareDialog();
+ ~ShareDialog() override;
private slots:
void done(int r) override;
diff --git a/src/gui/sharelinkwidget.cpp b/src/gui/sharelinkwidget.cpp
index 7a50639bf462..f0ea3c615799 100644
--- a/src/gui/sharelinkwidget.cpp
+++ b/src/gui/sharelinkwidget.cpp
@@ -20,6 +20,7 @@
#include "guiutility.h"
#include "sharemanager.h"
#include "theme.h"
+#include "elidedlabel.h"
#include "QProgressIndicator.h"
#include
@@ -78,11 +79,10 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
connect(_ui->confirmPassword, &QAbstractButton::clicked, this, &ShareLinkWidget::slotCreatePassword);
connect(_ui->confirmNote, &QAbstractButton::clicked, this, &ShareLinkWidget::slotCreateNote);
connect(_ui->confirmExpirationDate, &QAbstractButton::clicked, this, &ShareLinkWidget::slotSetExpireDate);
- connect(_ui->calendar, &QDateTimeEdit::dateChanged, this, &ShareLinkWidget::slotSetExpireDate);
_ui->errorLabel->hide();
- bool sharingPossible = true;
+ auto sharingPossible = true;
if (!_account->capabilities().sharePublicLink()) {
qCWarning(lcShareLink) << "Link shares have been disabled";
sharingPossible = false;
@@ -103,7 +103,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
togglePasswordOptions(false);
toggleExpireDateOptions(false);
toggleNoteOptions(false);
- _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1));
_ui->noteProgressIndicator->setVisible(false);
_ui->passwordProgressIndicator->setVisible(false);
@@ -122,7 +121,7 @@ ShareLinkWidget::~ShareLinkWidget()
delete _ui;
}
-void ShareLinkWidget::slotToggleShareLinkAnimation(bool start)
+void ShareLinkWidget::slotToggleShareLinkAnimation(const bool start)
{
_ui->sharelinkProgressIndicator->setVisible(start);
if (start) {
@@ -134,17 +133,19 @@ void ShareLinkWidget::slotToggleShareLinkAnimation(bool start)
}
}
-void ShareLinkWidget::slotToggleButtonAnimation(QToolButton *button, QProgressIndicator *progressIndicator, bool optionEnabled, bool start)
+void ShareLinkWidget::toggleButtonAnimation(QToolButton *button, QProgressIndicator *progressIndicator, const QAction *checkedAction) const
{
- button->setVisible(optionEnabled && !start);
- progressIndicator->setVisible(start);
- if (start) {
- if (!progressIndicator->isAnimated()) {
- progressIndicator->startAnimation();
- }
+ auto startAnimation = false;
+ const auto actionIsChecked = checkedAction->isChecked();
+ if (!progressIndicator->isAnimated() && actionIsChecked) {
+ progressIndicator->startAnimation();
+ startAnimation = true;
} else {
progressIndicator->stopAnimation();
}
+
+ button->setVisible(!startAnimation && actionIsChecked);
+ progressIndicator->setVisible(startAnimation && actionIsChecked);
}
void ShareLinkWidget::setLinkShare(QSharedPointer linkShare)
@@ -164,15 +165,15 @@ void ShareLinkWidget::focusPasswordLineEdit()
void ShareLinkWidget::setupUiOptions()
{
- connect(_linkShare.data(), &LinkShare::expireDateSet, this, &ShareLinkWidget::slotExpireDateSet);
connect(_linkShare.data(), &LinkShare::noteSet, this, &ShareLinkWidget::slotNoteSet);
connect(_linkShare.data(), &LinkShare::passwordSet, this, &ShareLinkWidget::slotPasswordSet);
connect(_linkShare.data(), &LinkShare::passwordSetError, this, &ShareLinkWidget::slotPasswordSetError);
+ connect(_linkShare.data(), &LinkShare::labelSet, this, &ShareLinkWidget::slotLabelSet);
// Prepare permissions check and create group action
const QDate expireDate = _linkShare.data()->getExpireDate().isValid() ? _linkShare.data()->getExpireDate() : QDate();
const SharePermissions perm = _linkShare.data()->getPermissions();
- bool checked = false;
+ auto checked = false;
auto *permissionsGroup = new QActionGroup(this);
// Prepare sharing menu
@@ -189,7 +190,7 @@ void ShareLinkWidget::setupUiOptions()
} else {
checked = (perm == SharePermissionRead);
- _readOnlyLinkAction = permissionsGroup->addAction(tr("Read only"));
+ _readOnlyLinkAction = permissionsGroup->addAction(tr("View only"));
_readOnlyLinkAction->setCheckable(true);
_readOnlyLinkAction->setChecked(checked);
@@ -204,6 +205,41 @@ void ShareLinkWidget::setupUiOptions()
_allowUploadLinkAction->setCheckable(true);
_allowUploadLinkAction->setChecked(checked);
}
+
+ _shareLinkElidedLabel = new OCC::ElidedLabel(this);
+ _shareLinkElidedLabel->setElideMode(Qt::ElideRight);
+ displayShareLinkLabel();
+ _ui->horizontalLayout->insertWidget(2, _shareLinkElidedLabel);
+
+ _shareLinkLayout = new QHBoxLayout(this);
+
+ _shareLinkLabel = new QLabel(this);
+ _shareLinkLabel->setPixmap(QString(":/client/theme/black/edit.svg"));
+ _shareLinkLayout->addWidget(_shareLinkLabel);
+
+ _shareLinkEdit = new QLineEdit(this);
+ connect(_shareLinkEdit, &QLineEdit::returnPressed, this, &ShareLinkWidget::slotCreateLabel);
+ _shareLinkEdit->setPlaceholderText(tr("Link name"));
+ _shareLinkEdit->setText(_linkShare.data()->getLabel());
+ _shareLinkLayout->addWidget(_shareLinkEdit);
+
+ _shareLinkButton = new QToolButton(this);
+ connect(_shareLinkButton, &QToolButton::clicked, this, &ShareLinkWidget::slotCreateLabel);
+ _shareLinkButton->setIcon(QIcon(":/client/theme/confirm.svg"));
+ _shareLinkButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ _shareLinkLayout->addWidget(_shareLinkButton);
+
+ _shareLinkProgressIndicator = new QProgressIndicator(this);
+ _shareLinkProgressIndicator->setVisible(false);
+ _shareLinkLayout->addWidget(_shareLinkProgressIndicator);
+
+ _shareLinkDefaultWidget = new QWidget(this);
+ _shareLinkDefaultWidget->setLayout(_shareLinkLayout);
+
+ _shareLinkWidgetAction = new QWidgetAction(this);
+ _shareLinkWidgetAction->setDefaultWidget(_shareLinkDefaultWidget);
+ _shareLinkWidgetAction->setCheckable(true);
+ _linkContextMenu->addAction(_shareLinkWidgetAction);
// Adds permissions actions (radio button style)
if (_isFile) {
@@ -221,7 +257,7 @@ void ShareLinkWidget::setupUiOptions()
if (_linkShare->getNote().isSimpleText() && !_linkShare->getNote().isEmpty()) {
_ui->textEdit_note->setText(_linkShare->getNote());
_noteLinkAction->setChecked(true);
- showNoteOptions(true);
+ toggleNoteOptions();
}
// Adds action to display password widget (check box)
@@ -231,7 +267,7 @@ void ShareLinkWidget::setupUiOptions()
if (_linkShare.data()->isPasswordSet()) {
_passwordProtectLinkAction->setChecked(true);
_ui->lineEdit_password->setPlaceholderText(QString::fromUtf8(passwordIsSetPlaceholder));
- showPasswordOptions(true);
+ togglePasswordOptions();
}
// If password is enforced then don't allow users to disable it
@@ -249,8 +285,11 @@ void ShareLinkWidget::setupUiOptions()
if (!expireDate.isNull()) {
_ui->calendar->setDate(expireDate);
_expirationDateLinkAction->setChecked(true);
- showExpireDateOptions(true);
+ toggleExpireDateOptions();
}
+ connect(_ui->calendar, &QDateTimeEdit::dateChanged, this, &ShareLinkWidget::slotSetExpireDate);
+ connect(_linkShare.data(), &LinkShare::expireDateSet, this, &ShareLinkWidget::slotExpireDateSet);
+
// If expiredate is enforced do not allow disable and set max days
if (_account->capabilities().sharePublicLinkEnforceExpireDate()) {
@@ -263,7 +302,7 @@ void ShareLinkWidget::setupUiOptions()
// Adds action to unshare widget (check box)
_unshareLinkAction = _linkContextMenu->addAction(QIcon(":/client/theme/delete.svg"),
- tr("Delete share link"));
+ tr("Delete link"));
_linkContextMenu->addSeparator();
@@ -285,32 +324,27 @@ void ShareLinkWidget::setupUiOptions()
// show sharing options
_ui->shareLinkToolButton->show();
- //TO DO
- //startAnimation(0, height());
-
customizeStyle();
}
-void ShareLinkWidget::setNote(const QString ¬e)
+void ShareLinkWidget::slotCreateNote()
{
- if (_linkShare) {
- slotToggleButtonAnimation(_ui->confirmNote, _ui->noteProgressIndicator, _noteLinkAction->isChecked(), true);
- _ui->errorLabel->hide();
- _linkShare->setNote(note);
+ const auto note = _ui->textEdit_note->toPlainText();
+ if (!_linkShare || _linkShare->getNote() == note || note.isEmpty()) {
+ return;
}
-}
-
-void ShareLinkWidget::slotCreateNote()
-{
- setNote(_ui->textEdit_note->toPlainText());
+
+ toggleButtonAnimation(_ui->confirmNote, _ui->noteProgressIndicator, _noteLinkAction);
+ _ui->errorLabel->hide();
+ _linkShare->setNote(note);
}
void ShareLinkWidget::slotNoteSet()
{
- slotToggleButtonAnimation(_ui->confirmNote, _ui->noteProgressIndicator, _noteLinkAction->isChecked(), false);
+ toggleButtonAnimation(_ui->confirmNote, _ui->noteProgressIndicator, _noteLinkAction);
}
-void ShareLinkWidget::slotCopyLinkShare(bool clicked)
+void ShareLinkWidget::slotCopyLinkShare(const bool clicked) const
{
Q_UNUSED(clicked);
@@ -319,7 +353,7 @@ void ShareLinkWidget::slotCopyLinkShare(bool clicked)
void ShareLinkWidget::slotExpireDateSet()
{
- slotToggleButtonAnimation(_ui->confirmExpirationDate, _ui->expirationDateProgressIndicator, _expirationDateLinkAction->isChecked(), false);
+ toggleButtonAnimation(_ui->confirmExpirationDate, _ui->expirationDateProgressIndicator, _expirationDateLinkAction);
}
void ShareLinkWidget::slotSetExpireDate()
@@ -328,7 +362,7 @@ void ShareLinkWidget::slotSetExpireDate()
return;
}
- slotToggleButtonAnimation(_ui->confirmExpirationDate, _ui->expirationDateProgressIndicator, _expirationDateLinkAction->isChecked(), true);
+ toggleButtonAnimation(_ui->confirmExpirationDate, _ui->expirationDateProgressIndicator, _expirationDateLinkAction);
_ui->errorLabel->hide();
_linkShare->setExpireDate(_ui->calendar->date());
}
@@ -339,12 +373,12 @@ void ShareLinkWidget::slotCreatePassword()
return;
}
- slotToggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction->isChecked(), true);
+ toggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction);
_ui->errorLabel->hide();
emit createPassword(_ui->lineEdit_password->text());
}
-void ShareLinkWidget::slotCreateShareLink(bool clicked)
+void ShareLinkWidget::slotCreateShareLink(const bool clicked)
{
Q_UNUSED(clicked);
slotToggleShareLinkAnimation(true);
@@ -353,27 +387,26 @@ void ShareLinkWidget::slotCreateShareLink(bool clicked)
void ShareLinkWidget::slotPasswordSet()
{
- slotToggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction->isChecked(), false);
+ toggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction);
+
+ _ui->lineEdit_password->setText({});
- _ui->lineEdit_password->setText(QString());
if (_linkShare->isPasswordSet()) {
_ui->lineEdit_password->setEnabled(true);
_ui->lineEdit_password->setPlaceholderText(QString::fromUtf8(passwordIsSetPlaceholder));
} else {
- _ui->lineEdit_password->setPlaceholderText(QString());
+ _ui->lineEdit_password->setPlaceholderText({});
}
- setupUiOptions();
-
emit createPasswordProcessed();
}
-void ShareLinkWidget::slotPasswordSetError(int code, const QString &message)
+void ShareLinkWidget::slotPasswordSetError(const int code, const QString &message)
{
- slotToggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction->isChecked(), false);
+ toggleButtonAnimation(_ui->confirmPassword, _ui->passwordProgressIndicator, _passwordProtectLinkAction);
slotServerError(code, message);
- showPasswordOptions(true);
+ togglePasswordOptions();
_ui->lineEdit_password->setFocus();
emit createPasswordProcessed();
}
@@ -398,9 +431,6 @@ void ShareLinkWidget::slotDeleteShareFetched()
{
slotToggleShareLinkAnimation(false);
- // TODO
- //startAnimation(height(), 0);
-
_linkShare.clear();
togglePasswordOptions(false);
toggleNoteOptions(false);
@@ -408,31 +438,40 @@ void ShareLinkWidget::slotDeleteShareFetched()
emit deleteLinkShare();
}
-void ShareLinkWidget::showNoteOptions(bool show)
+void ShareLinkWidget::toggleNoteOptions(const bool enable)
{
- _ui->noteLabel->setVisible(show);
- _ui->textEdit_note->setVisible(show);
- _ui->confirmNote->setVisible(show);
+ _ui->noteLabel->setVisible(enable);
+ _ui->textEdit_note->setVisible(enable);
+ _ui->confirmNote->setVisible(enable);
+ _ui->textEdit_note->setText(enable && _linkShare ? _linkShare->getNote() : QString());
+
+ if (!enable && _linkShare && !_linkShare->getNote().isEmpty()) {
+ _linkShare->setNote({});
+ }
}
-
-void ShareLinkWidget::toggleNoteOptions(bool enable)
+void ShareLinkWidget::slotAnimationFinished()
{
- showNoteOptions(enable);
+ emit resizeRequested();
+ deleteLater();
+}
- if (enable) {
- _ui->textEdit_note->setFocus();
- } else {
- // 'deletes' note
- if (_linkShare)
- _linkShare->setNote(QString());
+void ShareLinkWidget::slotCreateLabel()
+{
+ const auto labelText = _shareLinkEdit->text();
+ if (!_linkShare || _linkShare->getLabel() == labelText || labelText.isEmpty()) {
+ return;
}
+ _shareLinkWidgetAction->setChecked(true);
+ toggleButtonAnimation(_shareLinkButton, _shareLinkProgressIndicator, _shareLinkWidgetAction);
+ _ui->errorLabel->hide();
+ _linkShare->setLabel(_shareLinkEdit->text());
}
-void ShareLinkWidget::slotAnimationFinished()
+void ShareLinkWidget::slotLabelSet()
{
- emit resizeRequested();
- deleteLater();
+ toggleButtonAnimation(_shareLinkButton, _shareLinkProgressIndicator, _shareLinkWidgetAction);
+ displayShareLinkLabel();
}
void ShareLinkWidget::slotDeleteAnimationFinished()
@@ -447,7 +486,6 @@ void ShareLinkWidget::slotCreateShareRequiresPassword(const QString &message)
{
slotToggleShareLinkAnimation(message.isEmpty());
- showPasswordOptions(true);
if (!message.isEmpty()) {
_ui->errorLabel->setText(message);
_ui->errorLabel->show();
@@ -455,49 +493,36 @@ void ShareLinkWidget::slotCreateShareRequiresPassword(const QString &message)
_passwordRequired = true;
- togglePasswordOptions(true);
+ togglePasswordOptions();
}
-void ShareLinkWidget::showPasswordOptions(bool show)
+void ShareLinkWidget::togglePasswordOptions(const bool enable)
{
- _ui->passwordLabel->setVisible(show);
- _ui->lineEdit_password->setVisible(show);
- _ui->confirmPassword->setVisible(show);
-}
-
-void ShareLinkWidget::togglePasswordOptions(bool enable)
-{
- showPasswordOptions(enable);
-
- if (enable) {
- _ui->lineEdit_password->setFocus();
- } else {
- // 'deletes' password
- if (_linkShare)
- _linkShare->setPassword(QString());
+ _ui->passwordLabel->setVisible(enable);
+ _ui->lineEdit_password->setVisible(enable);
+ _ui->confirmPassword->setVisible(enable);
+ _ui->lineEdit_password->setFocus();
+
+ if (!enable && _linkShare && _linkShare->isPasswordSet()) {
+ _linkShare->setPassword({});
}
}
-void ShareLinkWidget::showExpireDateOptions(bool show)
-{
- _ui->expirationLabel->setVisible(show);
- _ui->calendar->setVisible(show);
- _ui->confirmExpirationDate->setVisible(show);
-}
-
-void ShareLinkWidget::toggleExpireDateOptions(bool enable)
+void ShareLinkWidget::toggleExpireDateOptions(const bool enable)
{
- showExpireDateOptions(enable);
-
- if (enable) {
- const QDate date = QDate::currentDate().addDays(1);
- _ui->calendar->setDate(date);
- _ui->calendar->setMinimumDate(date);
- _ui->calendar->setFocus();
- } else {
- // 'deletes' expire date
- if (_linkShare)
- _linkShare->setExpireDate(QDate());
+ _ui->expirationLabel->setVisible(enable);
+ _ui->calendar->setVisible(enable);
+ _ui->confirmExpirationDate->setVisible(enable);
+
+ const auto date = enable ? _linkShare->getExpireDate() : QDate::currentDate().addDays(1);
+ _ui->calendar->setDate(date);
+ _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1));
+ _ui->calendar->setMaximumDate(
+ QDate::currentDate().addDays(_account->capabilities().sharePublicLinkExpireDateDays()));
+ _ui->calendar->setFocus();
+
+ if (!enable && _linkShare && _linkShare->getExpireDate().isValid()) {
+ _linkShare->setExpireDate({});
}
}
@@ -542,7 +567,7 @@ void ShareLinkWidget::slotContextMenuButtonClicked()
void ShareLinkWidget::slotLinkContextMenuActionTriggered(QAction *action)
{
- bool state = action->isChecked();
+ const auto state = action->isChecked();
SharePermissions perm = SharePermissionRead;
if (action == _addAnotherLinkAction) {
@@ -577,7 +602,7 @@ void ShareLinkWidget::slotLinkContextMenuActionTriggered(QAction *action)
}
}
-void ShareLinkWidget::slotServerError(int code, const QString &message)
+void ShareLinkWidget::slotServerError(const int code, const QString &message)
{
slotToggleShareLinkAnimation(false);
@@ -615,4 +640,12 @@ void ShareLinkWidget::customizeStyle()
_ui->passwordProgressIndicator->setColor(QGuiApplication::palette().color(QPalette::Text));
}
+void ShareLinkWidget::displayShareLinkLabel()
+{
+ _shareLinkElidedLabel->clear();
+ if (!_linkShare->getLabel().isEmpty()) {
+ _shareLinkElidedLabel->setText(QString("(%1)").arg(_linkShare->getLabel()));
+ }
+}
+
}
diff --git a/src/gui/sharelinkwidget.h b/src/gui/sharelinkwidget.h
index a9087b6bc2d5..d9c3dec123cf 100644
--- a/src/gui/sharelinkwidget.h
+++ b/src/gui/sharelinkwidget.h
@@ -23,6 +23,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
class QMenu;
class QTableWidgetItem;
@@ -37,6 +41,7 @@ class AbstractCredentials;
class SyncResult;
class LinkShare;
class Share;
+class ElidedLabel;
/**
* @brief The ShareDialog class
@@ -52,7 +57,7 @@ class ShareLinkWidget : public QWidget
const QString &localPath,
SharePermissions maxSharingPermissions,
QWidget *parent = nullptr);
- ~ShareLinkWidget();
+ ~ShareLinkWidget() override;
void toggleButton(bool show);
void setupUiOptions();
@@ -64,20 +69,20 @@ class ShareLinkWidget : public QWidget
public slots:
void slotDeleteShareFetched();
- void slotToggleShareLinkAnimation(bool start);
- void slotToggleButtonAnimation(QToolButton *button, QProgressIndicator *progressIndicator, bool optionEnabled, bool start);
- void slotServerError(int code, const QString &message);
+ void slotToggleShareLinkAnimation(const bool start);
+ void slotServerError(const int code, const QString &message);
void slotCreateShareRequiresPassword(const QString &message);
void slotStyleChanged();
private slots:
- void slotCreateShareLink(bool clicked);
+ void slotCreateShareLink(const bool clicked);
+ void slotCopyLinkShare(const bool clicked) const;
void slotCreatePassword();
void slotPasswordSet();
- void slotPasswordSetError(int code, const QString &message);
+ void slotPasswordSetError(const int code, const QString &message);
- void slotCreateNote();
+ void slotCreateNote();
void slotNoteSet();
void slotSetExpireDate();
@@ -88,6 +93,9 @@ private slots:
void slotDeleteAnimationFinished();
void slotAnimationFinished();
+
+ void slotCreateLabel();
+ void slotLabelSet();
signals:
void createLinkShare();
@@ -99,18 +107,11 @@ private slots:
private:
void displayError(const QString &errMsg);
-
- void showPasswordOptions(bool show);
- void togglePasswordOptions(bool enable);
-
- void showNoteOptions(bool show);
- void toggleNoteOptions(bool enable);
- void setNote(const QString ¬e);
-
- void showExpireDateOptions(bool show);
- void toggleExpireDateOptions(bool enable);
-
- void slotCopyLinkShare(bool clicked);
+
+ void togglePasswordOptions(const bool enable = true);
+ void toggleNoteOptions(const bool enable = true);
+ void toggleExpireDateOptions(const bool enable = true);
+ void toggleButtonAnimation(QToolButton *button, QProgressIndicator *progressIndicator, const QAction *checkedAction) const;
/** Confirm with the user and then delete the share */
void confirmAndDeleteShare();
@@ -121,6 +122,8 @@ private slots:
void startAnimation(const int start, const int end);
void customizeStyle();
+
+ void displayShareLinkLabel();
Ui::ShareLinkWidget *_ui;
AccountPtr _account;
@@ -146,6 +149,14 @@ private slots:
QAction *_unshareLinkAction;
QAction *_addAnotherLinkAction;
QAction *_noteLinkAction;
+ QHBoxLayout *_shareLinkLayout{};
+ QLabel *_shareLinkLabel{};
+ ElidedLabel *_shareLinkElidedLabel{};
+ QLineEdit *_shareLinkEdit{};
+ QToolButton *_shareLinkButton{};
+ QProgressIndicator *_shareLinkProgressIndicator{};
+ QWidget *_shareLinkDefaultWidget{};
+ QWidgetAction *_shareLinkWidgetAction{};
};
}
diff --git a/src/gui/sharemanager.cpp b/src/gui/sharemanager.cpp
index 6f89eb5734c7..154bcbec3196 100644
--- a/src/gui/sharemanager.cpp
+++ b/src/gui/sharemanager.cpp
@@ -146,6 +146,12 @@ void Share::deleteShare()
job->deleteShare(getId());
}
+bool Share::isShareTypeUserGroupEmailRoomOrRemote(const ShareType type)
+{
+ return (type == Share::TypeUser || type == Share::TypeGroup || type == Share::TypeEmail || type == Share::TypeRoom
+ || type == Share::TypeRemote);
+}
+
void Share::slotDeleted()
{
updateFolder(_account, _path);
@@ -195,12 +201,16 @@ LinkShare::LinkShare(AccountPtr account,
Permissions permissions,
bool isPasswordSet,
const QUrl &url,
- const QDate &expireDate)
+ const QDate &expireDate,
+ const QString ¬e,
+ const QString &label)
: Share(account, id, uidowner, ownerDisplayName, path, Share::TypeLink, isPasswordSet, permissions)
, _name(name)
, _token(token)
+ , _note(note)
, _expireDate(expireDate)
, _url(url)
+ , _label(label)
{
}
@@ -224,20 +234,19 @@ QString LinkShare::getNote() const
return _note;
}
+QString LinkShare::getLabel() const
+{
+ return _label;
+}
+
void LinkShare::setName(const QString &name)
{
- auto *job = new OcsShareJob(_account);
- connect(job, &OcsShareJob::shareJobFinished, this, &LinkShare::slotNameSet);
- connect(job, &OcsJob::ocsError, this, &LinkShare::slotOcsError);
- job->setName(getId(), name);
+ createShareJob(&LinkShare::slotNameSet)->setName(getId(), name);
}
void LinkShare::setNote(const QString ¬e)
{
- auto *job = new OcsShareJob(_account);
- connect(job, &OcsShareJob::shareJobFinished, this, &LinkShare::slotNoteSet);
- connect(job, &OcsJob::ocsError, this, &LinkShare::slotOcsError);
- job->setNote(getId(), note);
+ createShareJob(&LinkShare::slotNoteSet)->setNote(getId(), note);
}
void LinkShare::slotNoteSet(const QJsonDocument &, const QVariant ¬e)
@@ -253,10 +262,20 @@ QString LinkShare::getToken() const
void LinkShare::setExpireDate(const QDate &date)
{
+ createShareJob(&LinkShare::slotExpireDateSet)->setExpireDate(getId(), date);
+}
+
+void LinkShare::setLabel(const QString &label)
+{
+ createShareJob(&LinkShare::slotLabelSet)->setLabel(getId(), label);
+}
+
+template
+OcsShareJob *LinkShare::createShareJob(const LinkShareSlot slotFunction) {
auto *job = new OcsShareJob(_account);
- connect(job, &OcsShareJob::shareJobFinished, this, &LinkShare::slotExpireDateSet);
+ connect(job, &OcsShareJob::shareJobFinished, this, slotFunction);
connect(job, &OcsJob::ocsError, this, &LinkShare::slotOcsError);
- job->setExpireDate(getId(), date);
+ return job;
}
void LinkShare::slotExpireDateSet(const QJsonDocument &reply, const QVariant &value)
@@ -281,6 +300,14 @@ void LinkShare::slotNameSet(const QJsonDocument &, const QVariant &value)
emit nameSet();
}
+void LinkShare::slotLabelSet(const QJsonDocument &, const QVariant &label)
+{
+ if (_label != label.toString()) {
+ _label = label.toString();
+ emit labelSet();
+ }
+}
+
UserGroupShare::UserGroupShare(AccountPtr account,
const QString &id,
const QString &owner,
@@ -296,7 +323,7 @@ UserGroupShare::UserGroupShare(AccountPtr account,
, _note(note)
, _expireDate(expireDate)
{
- Q_ASSERT(shareType == TypeUser || shareType == TypeGroup || shareType == TypeEmail);
+ Q_ASSERT(Share::isShareTypeUserGroupEmailRoomOrRemote(shareType));
Q_ASSERT(shareWith);
}
@@ -326,6 +353,11 @@ QDate UserGroupShare::getExpireDate() const
void UserGroupShare::setExpireDate(const QDate &date)
{
+ if (_expireDate == date) {
+ emit expireDateSet();
+ return;
+ }
+
auto *job = new OcsShareJob(_account);
connect(job, &OcsShareJob::shareJobFinished, this, &UserGroupShare::slotExpireDateSet);
connect(job, &OcsJob::ocsError, this, &UserGroupShare::slotOcsError);
@@ -461,7 +493,7 @@ void ShareManager::slotSharesFetched(const QJsonDocument &reply)
if (shareType == Share::TypeLink) {
newShare = parseLinkShare(data);
- } else if (shareType == Share::TypeGroup || shareType == Share::TypeUser || shareType == Share::TypeEmail) {
+ } else if (Share::isShareTypeUserGroupEmailRoomOrRemote(static_cast (shareType))) {
newShare = parseUserGroupShare(data);
} else {
newShare = parseShare(data);
@@ -524,6 +556,11 @@ QSharedPointer ShareManager::parseLinkShare(const QJsonObject &data)
if (data.value("expiration").isString()) {
expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00");
}
+
+ QString note;
+ if (data.value("note").isString()) {
+ note = data.value("note").toString();
+ }
return QSharedPointer(new LinkShare(_account,
data.value("id").toVariant().toString(), // "id" used to be an integer, support both
@@ -535,7 +572,9 @@ QSharedPointer ShareManager::parseLinkShare(const QJsonObject &data)
(Share::Permissions)data.value("permissions").toInt(),
data.value("share_with").isString(), // has password?
url,
- expireDate));
+ expireDate,
+ note,
+ data.value("label").toString()));
}
QSharedPointer ShareManager::parseShare(const QJsonObject &data)
diff --git a/src/gui/sharemanager.h b/src/gui/sharemanager.h
index a764163f63c3..a69ec449d985 100644
--- a/src/gui/sharemanager.h
+++ b/src/gui/sharemanager.h
@@ -31,6 +31,8 @@ class QJsonObject;
namespace OCC {
+class OcsShareJob;
+
class Share : public QObject
{
Q_OBJECT
@@ -128,6 +130,11 @@ class Share : public QObject
*/
void deleteShare();
+ /*
+ * Is it a share with a user or group (local or remote)
+ */
+ static bool isShareTypeUserGroupEmailRoomOrRemote(const ShareType type);
+
signals:
void permissionsSet();
void shareDeleted();
@@ -175,7 +182,9 @@ class LinkShare : public Share
const Permissions permissions,
bool isPasswordSet,
const QUrl &url,
- const QDate &expireDate);
+ const QDate &expireDate,
+ const QString ¬e,
+ const QString &label);
/*
* Get the share link
@@ -205,8 +214,12 @@ class LinkShare : public Share
/*
* Returns the note of the link share.
*/
-
QString getNote() const;
+
+ /*
+ * Returns the label of the link share.
+ */
+ QString getLabel() const;
/*
* Set the name of the link share.
@@ -215,7 +228,6 @@ class LinkShare : public Share
*/
void setName(const QString &name);
-
/*
* Set the note of the link share.
*/
@@ -238,16 +250,30 @@ class LinkShare : public Share
* In case of a server error the serverError signal is emitted.
*/
void setExpireDate(const QDate &expireDate);
-
+
+ /*
+ * Set the label of the share link.
+ */
+ void setLabel(const QString &label);
+
+ /*
+ * Create OcsShareJob and connect to signal/slots
+ */
+ template
+ OcsShareJob *createShareJob(const LinkShareSlot slotFunction);
+
+
signals:
void expireDateSet();
void noteSet();
void nameSet();
+ void labelSet();
private slots:
void slotNoteSet(const QJsonDocument &, const QVariant &value);
void slotExpireDateSet(const QJsonDocument &reply, const QVariant &value);
void slotNameSet(const QJsonDocument &, const QVariant &value);
+ void slotLabelSet(const QJsonDocument &, const QVariant &value);
private:
QString _name;
@@ -255,6 +281,7 @@ private slots:
QString _note;
QDate _expireDate;
QUrl _url;
+ QString _label;
};
class UserGroupShare : public Share
diff --git a/src/gui/shareusergroupwidget.cpp b/src/gui/shareusergroupwidget.cpp
index 47e6ebc6cca0..9c9bc3fc0627 100644
--- a/src/gui/shareusergroupwidget.cpp
+++ b/src/gui/shareusergroupwidget.cpp
@@ -12,7 +12,9 @@
* for more details.
*/
+#include "ocsprofileconnector.h"
#include "sharee.h"
+#include "tray/usermodel.h"
#include "ui_shareusergroupwidget.h"
#include "ui_shareuserline.h"
#include "shareusergroupwidget.h"
@@ -27,6 +29,7 @@
#include "thumbnailjob.h"
#include "sharemanager.h"
#include "theme.h"
+#include "iconutils.h"
#include "QProgressIndicator.h"
#include
@@ -35,7 +38,9 @@
#include
#include
#include
-#include
+#include
+#include
+#include
#include
#include
#include
@@ -46,15 +51,38 @@
#include
#include
#include
+#include
+#include
+#include
#include
namespace {
- const char *passwordIsSetPlaceholder = "●●●●●●●●";
+const char *passwordIsSetPlaceholder = "●●●●●●●●";
+
}
namespace OCC {
+AvatarEventFilter::AvatarEventFilter(QObject *parent)
+ : QObject(parent)
+{
+}
+
+
+bool AvatarEventFilter::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::ContextMenu) {
+ const auto contextMenuEvent = dynamic_cast(event);
+ if (!contextMenuEvent) {
+ return false;
+ }
+ emit contextMenu(contextMenuEvent->globalPos());
+ return true;
+ }
+ return QObject::eventFilter(obj, event);
+}
+
ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
const QString &sharePath,
const QString &localPath,
@@ -247,7 +275,7 @@ void ShareUserGroupWidget::slotSharesFetched(const QList>
}
- Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup || share->getShareType() == Share::TypeEmail);
+ Q_ASSERT(Share::isShareTypeUserGroupEmailRoomOrRemote(share->getShareType()));
auto userGroupShare = qSharedPointerDynamicCast(share);
auto *s = new ShareUserLine(_account, userGroupShare, _maxSharingPermissions, _isFile, _parentScrollArea);
connect(s, &ShareUserLine::resizeRequested, this, &ShareUserGroupWidget::slotAdjustScrollWidgetSize);
@@ -369,43 +397,30 @@ void ShareUserGroupWidget::slotCompleterActivated(const QModelIndex &index)
*/
_lastCreatedShareId = QString();
-
- if (sharee->type() == Sharee::Federated
- && _account->serverVersionInt() < Account::makeServerVersion(9, 1, 0)) {
- int permissions = SharePermissionRead | SharePermissionUpdate;
- if (!_isFile) {
- permissions |= SharePermissionCreate | SharePermissionDelete;
- }
- _manager->createShare(_sharePath, Share::ShareType(sharee->type()),
- sharee->shareWith(), SharePermission(permissions));
- } else {
- QString password;
- if (sharee->type() == Sharee::Email && _account->capabilities().shareEmailPasswordEnforced()) {
- _ui->shareeLineEdit->clear();
- // always show a dialog for password-enforced email shares
- bool ok = false;
-
- do {
- password = QInputDialog::getText(
- this,
- tr("Password for share required"),
- tr("Please enter a password for your email share:"),
- QLineEdit::Password,
- QString(),
- &ok);
- } while (password.isEmpty() && ok);
-
- if (!ok) {
- return;
- }
+
+ QString password;
+ if (sharee->type() == Sharee::Email && _account->capabilities().shareEmailPasswordEnforced()) {
+ _ui->shareeLineEdit->clear();
+ // always show a dialog for password-enforced email shares
+ bool ok = false;
+
+ do {
+ password = QInputDialog::getText(
+ this,
+ tr("Password for share required"),
+ tr("Please enter a password for your email share:"),
+ QLineEdit::Password,
+ QString(),
+ &ok);
+ } while (password.isEmpty() && ok);
+
+ if (!ok) {
+ return;
}
-
- // Default permissions on creation
- int permissions = SharePermissionCreate | SharePermissionUpdate
- | SharePermissionDelete | SharePermissionShare;
- _manager->createShare(_sharePath, Share::ShareType(sharee->type()),
- sharee->shareWith(), SharePermission(permissions), password);
}
+
+ _manager->createShare(_sharePath, Share::ShareType(sharee->type()),
+ sharee->shareWith(), _maxSharingPermissions, password);
_ui->shareeLineEdit->setEnabled(false);
_ui->shareeLineEdit->clear();
@@ -476,16 +491,14 @@ void ShareUserGroupWidget::activateShareeLineEdit()
_ui->shareeLineEdit->setFocus();
}
-ShareUserLine::ShareUserLine(AccountPtr account,
- QSharedPointer share,
- SharePermissions maxSharingPermissions,
- bool isFile,
- QWidget *parent)
+ShareUserLine::ShareUserLine(AccountPtr account, QSharedPointer share,
+ SharePermissions maxSharingPermissions, bool isFile, QWidget *parent)
: QWidget(parent)
, _ui(new Ui::ShareUserLine)
, _account(account)
, _share(share)
, _isFile(isFile)
+ , _profilePageMenu(account, share->getShareWith()->shareWith())
{
Q_ASSERT(_share);
_ui->setupUi(this);
@@ -501,7 +514,6 @@ ShareUserLine::ShareUserLine(AccountPtr account,
_ui->permissionsEdit->setEnabled(enabled);
connect(_ui->permissionsEdit, &QAbstractButton::clicked, this, &ShareUserLine::slotEditPermissionsChanged);
connect(_ui->noteConfirmButton, &QAbstractButton::clicked, this, &ShareUserLine::onNoteConfirmButtonClicked);
- connect(_ui->confirmExpirationDate, &QAbstractButton::clicked, this, &ShareUserLine::setExpireDate);
connect(_ui->calendar, &QDateTimeEdit::dateChanged, this, &ShareUserLine::setExpireDate);
connect(_share.data(), &UserGroupShare::noteSet, this, &ShareUserLine::disableProgessIndicatorAnimation);
@@ -521,10 +533,9 @@ ShareUserLine::ShareUserLine(AccountPtr account,
showNoteOptions(false);
- // email shares do not support notes and expiration dates
- const bool isNoteAndExpirationDateSupported = _share->getShareType() != Share::ShareType::TypeEmail;
+ const bool isNoteSupported = _share->getShareType() != Share::ShareType::TypeEmail && _share->getShareType() != Share::ShareType::TypeRoom;
- if (isNoteAndExpirationDateSupported) {
+ if (isNoteSupported) {
_noteLinkAction = new QAction(tr("Note to recipient"));
_noteLinkAction->setCheckable(true);
menu->addAction(_noteLinkAction);
@@ -537,7 +548,9 @@ ShareUserLine::ShareUserLine(AccountPtr account,
showExpireDateOptions(false);
- if (isNoteAndExpirationDateSupported) {
+ const bool isExpirationDateSupported = _share->getShareType() != Share::ShareType::TypeEmail;
+
+ if (isExpirationDateSupported) {
// email shares do not support expiration dates
_expirationDateLinkAction = new QAction(tr("Set expiration date"));
_expirationDateLinkAction->setCheckable(true);
@@ -545,9 +558,8 @@ ShareUserLine::ShareUserLine(AccountPtr account,
connect(_expirationDateLinkAction, &QAction::triggered, this, &ShareUserLine::toggleExpireDateOptions);
const auto expireDate = _share->getExpireDate().isValid() ? share.data()->getExpireDate() : QDate();
if (!expireDate.isNull()) {
- _ui->calendar->setDate(expireDate);
_expirationDateLinkAction->setChecked(true);
- showExpireDateOptions(true);
+ showExpireDateOptions(true, expireDate);
}
}
@@ -630,11 +642,22 @@ ShareUserLine::ShareUserLine(AccountPtr account,
_permissionReshare->setVisible(false);
}
+ const auto avatarEventFilter = new AvatarEventFilter(_ui->avatar);
+ connect(avatarEventFilter, &AvatarEventFilter::contextMenu, this, &ShareUserLine::onAvatarContextMenu);
+ _ui->avatar->installEventFilter(avatarEventFilter);
+
loadAvatar();
customizeStyle();
}
+void ShareUserLine::onAvatarContextMenu(const QPoint &globalPosition)
+{
+ if (_share->getShareType() == Share::TypeUser) {
+ _profilePageMenu.exec(globalPosition);
+ }
+}
+
void ShareUserLine::loadAvatar()
{
const int avatarSize = 36;
@@ -646,15 +669,28 @@ void ShareUserLine::loadAvatar()
_ui->avatar->setMaximumWidth(avatarSize);
_ui->avatar->setAlignment(Qt::AlignCenter);
+ setDefaultAvatar(avatarSize);
+
+ /* Start the network job to fetch the avatar data.
+ *
+ * Currently only regular users can have avatars.
+ */
+ if (_share->getShareWith()->type() == Sharee::User) {
+ auto *job = new AvatarJob(_share->account(), _share->getShareWith()->shareWith(), avatarSize, this);
+ connect(job, &AvatarJob::avatarPixmap, this, &ShareUserLine::slotAvatarLoaded);
+ job->start();
+ }
+}
+
+void ShareUserLine::setDefaultAvatar(int avatarSize)
+{
/* Create the fallback avatar.
*
* This will be shown until the avatar image data arrives.
*/
- const QByteArray hash = QCryptographicHash::hash(_ui->sharedWith->text().toUtf8(), QCryptographicHash::Md5);
- double hue = static_cast(hash[0]) / 255.;
// See core/js/placeholder.js for details on colors and styling
- const QColor bg = QColor::fromHslF(hue, 0.7, 0.68);
+ const auto backgroundColor = backgroundColorForShareeType(_share->getShareWith()->type());
const QString style = QString(R"(* {
color: #fff;
background-color: %1;
@@ -662,21 +698,19 @@ void ShareUserLine::loadAvatar()
text-align: center;
line-height: %2px;
font-size: %2px;
- })").arg(bg.name(), QString::number(avatarSize / 2));
+ })").arg(backgroundColor.name(), QString::number(avatarSize / 2));
_ui->avatar->setStyleSheet(style);
- // The avatar label is the first character of the user name.
- const QString text = _share->getShareWith()->displayName();
- _ui->avatar->setText(text.at(0).toUpper());
+ const auto pixmap = pixmapForShareeType(_share->getShareWith()->type(), backgroundColor);
- /* Start the network job to fetch the avatar data.
- *
- * Currently only regular users can have avatars.
- */
- if (_share->getShareWith()->type() == Sharee::User) {
- auto *job = new AvatarJob(_share->account(), _share->getShareWith()->shareWith(), avatarSize, this);
- connect(job, &AvatarJob::avatarPixmap, this, &ShareUserLine::slotAvatarLoaded);
- job->start();
+ if (!pixmap.isNull()) {
+ _ui->avatar->setPixmap(pixmap);
+ } else {
+ qCDebug(lcSharing) << "pixmap is null for share type: " << _share->getShareWith()->type();
+
+ // The avatar label is the first character of the user name.
+ const auto text = _share->getShareWith()->displayName();
+ _ui->avatar->setText(text.at(0).toUpper());
}
}
@@ -926,13 +960,57 @@ void ShareUserLine::customizeStyle()
_deleteShareButton->setIcon(deleteicon);
_ui->noteConfirmButton->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
- _ui->confirmExpirationDate->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
_ui->progressIndicator->setColor(QGuiApplication::palette().color(QPalette::WindowText));
// make sure to force BackgroundRole to QPalette::WindowText for a lable, because it's parent always has a different role set that applies to children unless customized
_ui->errorLabel->setBackgroundRole(QPalette::WindowText);
}
+QPixmap ShareUserLine::pixmapForShareeType(Sharee::Type type, const QColor &backgroundColor) const
+{
+ switch (type) {
+ case Sharee::Room:
+ return Ui::IconUtils::pixmapForBackground(QStringLiteral("talk-app.svg"), backgroundColor);
+ case Sharee::Email:
+ return Ui::IconUtils::pixmapForBackground(QStringLiteral("email.svg"), backgroundColor);
+ case Sharee::Group:
+ case Sharee::Federated:
+ case Sharee::Circle:
+ case Sharee::User:
+ break;
+ }
+
+ return {};
+}
+
+QColor ShareUserLine::backgroundColorForShareeType(Sharee::Type type) const
+{
+ switch (type) {
+ case Sharee::Room:
+ return Theme::instance()->wizardHeaderBackgroundColor();
+ case Sharee::Email:
+ return Theme::instance()->wizardHeaderTitleColor();
+ case Sharee::Group:
+ case Sharee::Federated:
+ case Sharee::Circle:
+ case Sharee::User:
+ break;
+ }
+
+ const auto calculateBackgroundBasedOnText = [this]() {
+ const auto hash = QCryptographicHash::hash(_ui->sharedWith->text().toUtf8(), QCryptographicHash::Md5);
+ Q_ASSERT(hash.size() > 0);
+ if (hash.size() == 0) {
+ qCWarning(lcSharing) << "Failed to calculate hash color for share:" << _share->path();
+ return QColor{};
+ }
+ const double hue = static_cast(hash[0]) / 255.;
+ return QColor::fromHslF(hue, 0.7, 0.68);
+ };
+
+ return calculateBackgroundBasedOnText();
+}
+
void ShareUserLine::showNoteOptions(bool show)
{
_ui->noteLabel->setVisible(show);
@@ -979,17 +1057,21 @@ void ShareUserLine::toggleExpireDateOptions(bool enable)
}
}
-void ShareUserLine::showExpireDateOptions(bool show)
+void ShareUserLine::showExpireDateOptions(bool show, const QDate &initialDate)
{
_ui->expirationLabel->setVisible(show);
_ui->calendar->setVisible(show);
- _ui->confirmExpirationDate->setVisible(show);
if (show) {
- const QDate date = QDate::currentDate().addDays(1);
- _ui->calendar->setDate(date);
- _ui->calendar->setMinimumDate(date);
+ _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1));
+ _ui->calendar->setDate(initialDate.isValid() ? initialDate : _ui->calendar->minimumDate());
_ui->calendar->setFocus();
+
+ if (enforceExpirationDateForShare(_share->getShareType())) {
+ _ui->calendar->setMaximumDate(maxExpirationDateForShare(_share->getShareType(), _ui->calendar->maximumDate()));
+ _expirationDateLinkAction->setChecked(true);
+ _expirationDateLinkAction->setEnabled(false);
+ }
}
emit resizeRequested();
@@ -1031,6 +1113,35 @@ void ShareUserLine::disableProgessIndicatorAnimation()
enableProgessIndicatorAnimation(false);
}
+QDate ShareUserLine::maxExpirationDateForShare(const Share::ShareType type, const QDate &fallbackDate) const
+{
+ auto daysToExpire = 0;
+ if (type == Share::ShareType::TypeRemote) {
+ daysToExpire = _account->capabilities().shareRemoteExpireDateDays();
+ } else if (type == Share::ShareType::TypeEmail) {
+ daysToExpire = _account->capabilities().sharePublicLinkExpireDateDays();
+ } else {
+ daysToExpire = _account->capabilities().shareInternalExpireDateDays();
+ }
+
+ if (daysToExpire > 0) {
+ return QDate::currentDate().addDays(daysToExpire);
+ }
+
+ return fallbackDate;
+}
+
+bool ShareUserLine::enforceExpirationDateForShare(const Share::ShareType type) const
+{
+ if (type == Share::ShareType::TypeRemote) {
+ return _account->capabilities().shareRemoteEnforceExpireDate();
+ } else if (type == Share::ShareType::TypeEmail) {
+ return _account->capabilities().sharePublicLinkEnforceExpireDate();
+ }
+
+ return _account->capabilities().shareInternalEnforceExpireDate();
+}
+
void ShareUserLine::setPasswordConfirmed()
{
if (_ui->lineEdit_password->text().isEmpty()) {
diff --git a/src/gui/shareusergroupwidget.h b/src/gui/shareusergroupwidget.h
index bb7f54998f2b..599ab521b557 100644
--- a/src/gui/shareusergroupwidget.h
+++ b/src/gui/shareusergroupwidget.h
@@ -19,6 +19,7 @@
#include "sharemanager.h"
#include "sharepermissions.h"
#include "sharee.h"
+#include "profilepagewidget.h"
#include "QProgressIndicator.h"
#include
#include
@@ -26,6 +27,7 @@
#include
#include
#include
+#include
#include
class QAction;
@@ -44,6 +46,21 @@ class SyncResult;
class Share;
class ShareManager;
+class AvatarEventFilter : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit AvatarEventFilter(QObject *parent = nullptr);
+
+signals:
+ void clicked();
+ void contextMenu(const QPoint &globalPosition);
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+};
+
/**
* @brief The ShareDialog (user/group) class
* @ingroup gui
@@ -59,7 +76,7 @@ class ShareUserGroupWidget : public QWidget
SharePermissions maxSharingPermissions,
const QString &privateLinkUrl,
QWidget *parent = nullptr);
- ~ShareUserGroupWidget();
+ ~ShareUserGroupWidget() override;
signals:
void togglePublicLinkShare(bool);
@@ -128,7 +145,7 @@ class ShareUserLine : public QWidget
SharePermissions maxSharingPermissions,
bool isFile,
QWidget *parent = nullptr);
- ~ShareUserLine();
+ ~ShareUserLine() override;
QSharedPointer share() const;
@@ -166,18 +183,24 @@ private slots:
void slotConfirmPasswordClicked();
+ void onAvatarContextMenu(const QPoint &globalPosition);
+
private:
void displayPermissions();
void loadAvatar();
+ void setDefaultAvatar(int avatarSize);
void customizeStyle();
+ QPixmap pixmapForShareeType(Sharee::Type type, const QColor &backgroundColor = QColor()) const;
+ QColor backgroundColorForShareeType(Sharee::Type type) const;
+
void showNoteOptions(bool show);
void toggleNoteOptions(bool enable);
void onNoteConfirmButtonClicked();
void setNote(const QString ¬e);
void toggleExpireDateOptions(bool enable);
- void showExpireDateOptions(bool show);
+ void showExpireDateOptions(bool show, const QDate &initialDate = QDate());
void setExpireDate();
void togglePasswordSetProgressAnimation(bool show);
@@ -185,11 +208,16 @@ private slots:
void enableProgessIndicatorAnimation(bool enable);
void disableProgessIndicatorAnimation();
+ QDate maxExpirationDateForShare(const Share::ShareType type, const QDate &fallbackDate) const;
+ bool enforceExpirationDateForShare(const Share::ShareType type) const;
+
Ui::ShareUserLine *_ui;
AccountPtr _account;
QSharedPointer _share;
bool _isFile;
+ ProfilePageMenu _profilePageMenu;
+
// _permissionEdit is a checkbox
QAction *_permissionReshare;
QAction *_deleteShareButton;
diff --git a/src/gui/shareuserline.ui b/src/gui/shareuserline.ui
index 5c811ed5740f..5067a31201dd 100644
--- a/src/gui/shareuserline.ui
+++ b/src/gui/shareuserline.ui
@@ -6,8 +6,8 @@
0
0
- 980
- 239
+ 899
+ 310
@@ -273,20 +273,6 @@
- -
-
-
- …
-
-
-
- :/client/theme/confirm.svg:/client/theme/confirm.svg
-
-
- true
-
-
-
-
@@ -315,33 +301,519 @@
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 65
+ 70
+ 84
+
+
+
+
+
+
+ 95
+ 103
+ 127
+
+
+
+
+ 49
+ 49
+ 49
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 25
+ 25
+ 25
+
+
+
+
+
+
255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 64
+ 69
+ 82
+
+
+
+
+
+
+ 56
+ 60
+ 74
+
+
+
+
+
+
+ 0
0
0
+
+
+
+ 82
+ 148
+ 226
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 157
+ 255
+
+
+
+
+
+
+ 158
+ 79
+ 255
+
+
+
+
+
+
+ 60
+ 67
+ 79
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 238
+ 252
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 65
+ 70
+ 84
+
+
+
+
+
+
+ 95
+ 103
+ 127
+
+
+
+
+
+
+ 49
+ 49
+ 49
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 25
+ 25
+ 25
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 64
+ 69
+ 82
+
+
+
+
+
+
+ 56
+ 60
+ 74
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 82
+ 149
+ 225
+
+
+
+
255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 157
+ 255
+
+
+
+
+
+
+ 158
+ 79
+ 255
+
+
+
+
+
+
+ 60
+ 67
+ 79
+
+
+
+
+
+
+ 0
0
0
+
+
+
+ 238
+ 252
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
- 123
- 121
- 134
+ 65
+ 70
+ 84
+
+
+
+
+
+
+ 95
+ 103
+ 127
+
+
+
+
+
+
+ 49
+ 49
+ 49
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 25
+ 25
+ 25
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 64
+ 69
+ 82
+
+
+
+
+
+
+ 56
+ 60
+ 74
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 82
+ 148
+ 226
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 157
+ 255
+
+
+
+
+
+
+ 158
+ 79
+ 255
+
+
+
+
+
+
+ 60
+ 67
+ 79
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 238
+ 252
+ 255
+
+
+
+
+
+
+ 255
+ 255
+ 255
diff --git a/src/gui/socketapi/CMakeLists.txt b/src/gui/socketapi/CMakeLists.txt
new file mode 100644
index 000000000000..9290269eedab
--- /dev/null
+++ b/src/gui/socketapi/CMakeLists.txt
@@ -0,0 +1,8 @@
+target_sources(nextcloudCore PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/socketapi.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/socketuploadjob.cpp
+)
+
+if( APPLE )
+ target_sources(nextcloudCore PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/socketapisocket_mac.mm)
+endif()
diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi/socketapi.cpp
similarity index 82%
rename from src/gui/socketapi.cpp
rename to src/gui/socketapi/socketapi.cpp
index 16b618868262..9be00d22fb66 100644
--- a/src/gui/socketapi.cpp
+++ b/src/gui/socketapi/socketapi.cpp
@@ -16,9 +16,11 @@
#include "socketapi.h"
#include "socketapi_p.h"
+#include "socketapi/socketuploadjob.h"
#include "conflictdialog.h"
#include "conflictsolver.h"
+
#include "config.h"
#include "configfile.h"
#include "folderman.h"
@@ -32,6 +34,7 @@
#include "account.h"
#include "accountstate.h"
#include "account.h"
+#include "accountmanager.h"
#include "capabilities.h"
#include "common/asserts.h"
#include "guiutility.h"
@@ -57,6 +60,7 @@
#include
+#include
#include
#include
#include
@@ -78,12 +82,25 @@
#define MIRALL_SOCKET_API_VERSION "1.1"
namespace {
+
+const QLatin1Char RecordSeparator()
+{
+ return QLatin1Char('\x1e');
+}
+
+QStringList split(const QString &data)
+{
+ // TODO: string ref?
+ return data.split(RecordSeparator());
+}
+
#if GUI_TESTING
using namespace OCC;
-QList allObjects(const QList &widgets) {
- QList objects;
+QList allObjects(const QList &widgets)
+{
+ QList objects;
std::copy(widgets.constBegin(), widgets.constEnd(), std::back_inserter(objects));
objects << qApp;
@@ -91,11 +108,11 @@ QList allObjects(const QList &widgets) {
return objects;
}
-QObject *findWidget(const QString &queryString, const QList &widgets = QApplication::allWidgets())
+QObject *findWidget(const QString &queryString, const QList &widgets = QApplication::allWidgets())
{
auto objects = allObjects(widgets);
- QList::const_iterator foundWidget;
+ QList::const_iterator foundWidget;
if (queryString.contains('>')) {
qCDebug(lcSocketApi) << "queryString contains >";
@@ -107,33 +124,34 @@ QObject *findWidget(const QString &queryString, const QList &widgets =
qCDebug(lcSocketApi) << "Find parent: " << parentQueryString;
auto parent = findWidget(parentQueryString);
- if(!parent) {
+ if (!parent) {
return nullptr;
}
auto childQueryString = subQueries[1].trimmed();
- auto child = findWidget(childQueryString, parent->findChildren());
+ auto child = findWidget(childQueryString, parent->findChildren());
qCDebug(lcSocketApi) << "found child: " << !!child;
return child;
- } else if(queryString.startsWith('#')) {
+ } else if (queryString.startsWith('#')) {
auto objectName = queryString.mid(1);
qCDebug(lcSocketApi) << "find objectName: " << objectName;
foundWidget = std::find_if(objects.constBegin(), objects.constEnd(), [&](QObject *widget) {
return widget->objectName() == objectName;
});
} else {
- QList matches;
- std::copy_if(objects.constBegin(), objects.constEnd(), std::back_inserter(matches), [&](QObject* widget) {
+ QList matches;
+ std::copy_if(objects.constBegin(), objects.constEnd(), std::back_inserter(matches), [&](QObject *widget) {
return widget->inherits(queryString.toLatin1());
});
- std::for_each(matches.constBegin(), matches.constEnd(), [](QObject* w) {
- if(!w) return;
+ std::for_each(matches.constBegin(), matches.constEnd(), [](QObject *w) {
+ if (!w)
+ return;
qCDebug(lcSocketApi) << "WIDGET: " << w->objectName() << w->metaObject()->className();
});
- if(matches.empty()) {
+ if (matches.empty()) {
return nullptr;
}
return matches[0];
@@ -200,16 +218,6 @@ void SocketListener::sendMessage(const QString &message, bool doWait) const
}
}
-struct ListenerHasSocketPred
-{
- QIODevice *socket;
- ListenerHasSocketPred(QIODevice *socket)
- : socket(socket)
- {
- }
- bool operator()(const SocketListener &listener) const { return listener.socket == socket; }
-};
-
SocketApi::SocketApi(QObject *parent)
: QObject(parent)
{
@@ -217,6 +225,7 @@ SocketApi::SocketApi(QObject *parent)
qRegisterMetaType("SocketListener*");
qRegisterMetaType>("QSharedPointer");
+ qRegisterMetaType>("QSharedPointer");
if (Utility::isWindows()) {
socketPath = QLatin1String(R"(\\.\pipe\)")
@@ -236,21 +245,20 @@ SocketApi::SocketApi(QObject *parent)
CFURLRef url = (CFURLRef)CFAutorelease((CFURLRef)CFBundleCopyBundleURL(CFBundleGetMainBundle()));
QString bundlePath = QUrl::fromCFURL(url).path();
- auto _system = [](const QString &cmd, const QStringList &args){
+ auto _system = [](const QString &cmd, const QStringList &args) {
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
process.start(cmd, args);
- if (!process.waitForFinished())
- {
+ if (!process.waitForFinished()) {
qCWarning(lcSocketApi) << "Failed to load shell extension:" << cmd << args.join(" ") << process.errorString();
} else {
- qCInfo(lcSocketApi) << (process.exitCode() != 0 ? "Failed to load" : "Loaded") << "shell extension:" << cmd << args.join(" ") << process.readAll();
+ qCInfo(lcSocketApi) << (process.exitCode() != 0 ? "Failed to load" : "Loaded") << "shell extension:" << cmd << args.join(" ") << process.readAll();
}
};
// Add it again. This was needed for Mojave to trigger a load.
- _system(QStringLiteral("pluginkit"), {QStringLiteral("-a"),QStringLiteral("%1Contents/PlugIns/FinderSyncExt.appex/").arg(bundlePath)});
+ _system(QStringLiteral("pluginkit"), { QStringLiteral("-a"), QStringLiteral("%1Contents/PlugIns/FinderSyncExt.appex/").arg(bundlePath) });
// Tell Finder to use the Extension (checking it from System Preferences -> Extensions)
- _system(QStringLiteral("pluginkit"), {QStringLiteral("-e"), QStringLiteral("use"), QStringLiteral("-i"), QStringLiteral(APPLICATION_REV_DOMAIN ".FinderSyncExt")});
+ _system(QStringLiteral("pluginkit"), { QStringLiteral("-e"), QStringLiteral("use"), QStringLiteral("-i"), QStringLiteral(APPLICATION_REV_DOMAIN ".FinderSyncExt") });
#endif
} else if (Utility::isLinux() || Utility::isBSD()) {
@@ -288,7 +296,7 @@ SocketApi::~SocketApi()
qCDebug(lcSocketApi) << "dtor";
_localServer.close();
// All remaining sockets will be destroyed with _localServer, their parent
- ASSERT(_listeners.isEmpty() || _listeners.first().socket->parent() == &_localServer);
+ ASSERT(_listeners.isEmpty() || _listeners.first()->socket->parent() == &_localServer)
_listeners.clear();
}
@@ -307,14 +315,13 @@ void SocketApi::slotNewConnection()
connect(socket, &QObject::destroyed, this, &SocketApi::slotSocketDestroyed);
ASSERT(socket->readAll().isEmpty());
- _listeners.append(SocketListener(socket));
- SocketListener &listener = _listeners.last();
-
- foreach (Folder *f, FolderMan::instance()->map()) {
+ auto listener = QSharedPointer::create(socket);
+ _listeners.insert(socket, listener);
+ for (Folder *f : FolderMan::instance()->map()) {
if (f->canSync()) {
QString message = buildRegisterPathMessage(removeTrailingSlash(f->path()));
- qCInfo(lcSocketApi) << "Trying to send SocketAPI Register Path Message -->" << message << "to" << listener.socket;
- listener.sendMessage(message);
+ qCInfo(lcSocketApi) << "Trying to send SocketAPI Register Path Message -->" << message << "to" << listener->socket;
+ listener->sendMessage(message);
}
}
}
@@ -326,13 +333,13 @@ void SocketApi::onLostConnection()
auto socket = qobject_cast(sender());
ASSERT(socket);
- _listeners.erase(std::remove_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket)), _listeners.end());
+ _listeners.remove(socket);
}
void SocketApi::slotSocketDestroyed(QObject *obj)
{
auto *socket = static_cast(obj);
- _listeners.erase(std::remove_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket)), _listeners.end());
+ _listeners.remove(socket);
}
void SocketApi::slotReadSocket()
@@ -346,36 +353,38 @@ void SocketApi::slotReadSocket()
// the readyRead() signals are received - in that case there won't be a
// valid listener. We execute the handler anyway, but it will work with
// a SocketListener that doesn't send any messages.
- static auto noListener = SocketListener(nullptr);
- SocketListener *listener = &noListener;
- auto listenerIt = std::find_if(_listeners.begin(), _listeners.end(), ListenerHasSocketPred(socket));
- if (listenerIt != _listeners.end()) {
- listener = &*listenerIt;
- }
-
+ static auto invalidListener = QSharedPointer::create(nullptr);
+ const auto listener = _listeners.value(socket, invalidListener);
while (socket->canReadLine()) {
// Make sure to normalize the input from the socket to
// make sure that the path will match, especially on OS X.
- QString line = QString::fromUtf8(socket->readLine()).normalized(QString::NormalizationForm_C);
- line.chop(1); // remove the '\n'
+ const QString line = QString::fromUtf8(socket->readLine().trimmed()).normalized(QString::NormalizationForm_C);
qCInfo(lcSocketApi) << "Received SocketAPI message <--" << line << "from" << socket;
- QByteArray command = line.split(":").value(0).toLatin1();
-
- QByteArray functionWithArguments = "command_" + command;
- if (command.startsWith("ASYNC_")) {
- functionWithArguments += "(QSharedPointer)";
- } else {
- functionWithArguments += "(QString,SocketListener*)";
- }
-
- int indexOfMethod = staticMetaObject.indexOfMethod(functionWithArguments);
+ const int argPos = line.indexOf(QLatin1Char(':'));
+ const QByteArray command = line.midRef(0, argPos).toUtf8().toUpper();
+ const int indexOfMethod = [&] {
+ QByteArray functionWithArguments = QByteArrayLiteral("command_");
+ if (command.startsWith("ASYNC_")) {
+ functionWithArguments += command + QByteArrayLiteral("(QSharedPointer)");
+ } else if (command.startsWith("V2/")) {
+ functionWithArguments += QByteArrayLiteral("V2_") + command.mid(3) + QByteArrayLiteral("(QSharedPointer)");
+ } else {
+ functionWithArguments += command + QByteArrayLiteral("(QString,SocketListener*)");
+ }
+ Q_ASSERT(staticQtMetaObject.normalizedSignature(functionWithArguments) == functionWithArguments);
+ const auto out = staticMetaObject.indexOfMethod(functionWithArguments);
+ if (out == -1) {
+ listener->sendError(QStringLiteral("Function %1 not found").arg(QString::fromUtf8(functionWithArguments)));
+ }
+ ASSERT(out != -1)
+ return out;
+ }();
- QString argument = line.remove(0, command.length() + 1);
+ const auto argument = argPos != -1 ? line.midRef(argPos + 1) : QStringRef();
if (command.startsWith("ASYNC_")) {
-
auto arguments = argument.split('|');
if (arguments.size() != 2) {
- listener->sendMessage(QLatin1String("argument count is wrong"));
+ listener->sendError(QStringLiteral("argument count is wrong"));
return;
}
@@ -384,25 +393,41 @@ void SocketApi::slotReadSocket()
auto jobId = arguments[0];
auto socketApiJob = QSharedPointer(
- new SocketApiJob(jobId, listener, json), &QObject::deleteLater);
+ new SocketApiJob(jobId.toString(), listener, json), &QObject::deleteLater);
if (indexOfMethod != -1) {
staticMetaObject.method(indexOfMethod)
.invoke(this, Qt::QueuedConnection,
- Q_ARG(QSharedPointer, socketApiJob));
+ Q_ARG(QSharedPointer, socketApiJob));
} else {
qCWarning(lcSocketApi) << "The command is not supported by this version of the client:" << command
- << "with argument:" << argument;
- socketApiJob->reject("command not found");
+ << "with argument:" << argument;
+ socketApiJob->reject(QStringLiteral("command not found"));
+ }
+ } else if (command.startsWith("V2/")) {
+ QJsonParseError error;
+ const auto json = QJsonDocument::fromJson(argument.toUtf8(), &error).object();
+ if (error.error != QJsonParseError::NoError) {
+ qCWarning(lcSocketApi()) << "Invalid json" << argument.toString() << error.errorString();
+ listener->sendError(error.errorString());
+ return;
+ }
+ auto socketApiJob = QSharedPointer