├── .gitignore ├── .gitmodules ├── 3rdparty ├── Win_x64 │ ├── mingw │ │ ├── libcrypto-1_1-x64.dll │ │ ├── libgcc_s_seh-1.dll │ │ ├── libssl-1_1-x64.dll │ │ ├── libstdc++-6.dll │ │ └── libwinpthread-1.dll │ └── msvc │ │ ├── libcrypto-1_1-x64.dll │ │ └── libssl-1_1-x64.dll └── Win_x86 │ ├── mingw │ ├── libcrypto-1_1.dll │ └── libssl-1_1.dll │ └── msvc │ ├── libcrypto-1_1.dll │ └── libssl-1_1.dll ├── CMakeLists.txt ├── README.md └── src ├── CMakeLists.txt ├── component ├── CircularReveal.cpp ├── CircularReveal.h ├── TextAreaDocument.cpp └── TextAreaDocument.h ├── controller ├── ContactController.cpp └── ContactController.h ├── db ├── Message.cpp ├── Message.h ├── Session.cpp ├── Session.h ├── export.h └── precompiled.h ├── event ├── MainEvent.cpp └── MainEvent.h ├── helper ├── EmoticonHelper.cpp ├── EmoticonHelper.h ├── SettingsHelper.cpp ├── SettingsHelper.h ├── TextDocumentHelper.cpp └── TextDocumentHelper.h ├── main.cpp ├── manager ├── DBManager.cpp ├── DBManager.h ├── IMManager.cpp └── IMManager.h ├── model ├── BaseListModel.h ├── ContactListModel.cpp ├── ContactListModel.h ├── EmoticonListModel.cpp ├── EmoticonListModel.h ├── ImageModel.cpp ├── ImageModel.h ├── MessageListModel.cpp ├── MessageListModel.h ├── MessageModel.cpp ├── MessageModel.h ├── SessionListModel.cpp ├── SessionListModel.h ├── SessionModel.cpp ├── SessionModel.h ├── UserModel.cpp └── UserModel.h ├── proto ├── Message.pb.cc ├── Message.pb.h ├── ReplyBody.pb.cc ├── ReplyBody.pb.h ├── SentBody.pb.cc └── SentBody.pb.h ├── provider ├── UserProvider.cpp └── UserProvider.h ├── qml.qrc ├── res ├── image │ ├── avatar_default.png │ └── emoji │ │ ├── emoji_00.png │ │ ├── emoji_01.png │ │ ├── emoji_02.png │ │ ├── emoji_03.png │ │ ├── emoji_04.png │ │ ├── emoji_05.png │ │ ├── emoji_06.png │ │ ├── emoji_07.png │ │ ├── emoji_08.png │ │ ├── emoji_09.png │ │ ├── emoji_10.png │ │ ├── emoji_11.png │ │ ├── emoji_12.png │ │ ├── emoji_13.png │ │ ├── emoji_14.png │ │ ├── emoji_15.png │ │ ├── emoji_16.png │ │ ├── emoji_17.png │ │ ├── emoji_18.png │ │ ├── emoji_19.png │ │ ├── emoji_20.png │ │ ├── emoji_21.png │ │ ├── emoji_22.png │ │ ├── emoji_23.png │ │ ├── emoji_24.png │ │ ├── emoji_25.png │ │ ├── emoji_26.png │ │ ├── emoji_27.png │ │ ├── emoji_28.png │ │ ├── emoji_29.png │ │ ├── emoji_30.png │ │ ├── emoji_31.png │ │ ├── emoji_32.png │ │ ├── emoji_33.png │ │ ├── emoji_34.png │ │ ├── emoji_35.png │ │ ├── emoji_36.png │ │ ├── emoji_37.png │ │ ├── emoji_38.png │ │ ├── emoji_39.png │ │ ├── emoji_40.png │ │ ├── emoji_41.png │ │ ├── emoji_42.png │ │ ├── emoji_43.png │ │ ├── emoji_44.png │ │ ├── emoji_45.png │ │ ├── emoji_46.png │ │ ├── emoji_47.png │ │ ├── emoji_48.png │ │ ├── emoji_49.png │ │ ├── emoji_50.png │ │ ├── emoji_51.png │ │ ├── emoji_52.png │ │ ├── emoji_53.png │ │ ├── emoji_54.png │ │ ├── emoji_55.png │ │ ├── emoji_56.png │ │ ├── emoji_57.png │ │ ├── emoji_58.png │ │ ├── emoji_59.png │ │ ├── emoji_60.png │ │ ├── emoji_61.png │ │ ├── emoji_62.png │ │ ├── emoji_63.png │ │ ├── emoji_64.png │ │ ├── emoji_65.png │ │ ├── emoji_66.png │ │ ├── emoji_67.png │ │ └── emoji_68.png └── qml │ ├── App.qml │ ├── component │ ├── AvatarView.qml │ └── EmojiPanel.qml │ ├── page │ ├── ContactsPage.qml │ ├── SearchPage.qml │ └── SessionPage.qml │ └── window │ ├── LoginWindow.qml │ ├── MainWindow.qml │ ├── RegisterWindow.qml │ └── SettingWindow.qml ├── singleton.h └── stdafx.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Qt-es 2 | object_script.*.Release 3 | object_script.*.Debug 4 | *_plugin_import.cpp 5 | /.qmake.cache 6 | /.qmake.stash 7 | *.pro.user 8 | *.pro.user.* 9 | *.qbs.user 10 | *.qbs.user.* 11 | *.moc 12 | moc_*.cpp 13 | moc_*.h 14 | qrc_*.cpp 15 | ui_*.h 16 | *.qmlc 17 | *.jsc 18 | Makefile* 19 | #*build-* 20 | 21 | # Qt unit tests 22 | target_wrapper.* 23 | 24 | # QtCreator 25 | *.autosave 26 | 27 | # QtCreator Qml 28 | *.qmlproject.user 29 | *.qmlproject.user.* 30 | 31 | # QtCreator CMake 32 | CMakeLists.txt.user* 33 | 34 | bin 35 | .DS_Store 36 | build 37 | cmake-build-* 38 | .idea 39 | 40 | example/Version.h 41 | 42 | action-cli 43 | dist -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "FluentUI"] 2 | path = FluentUI 3 | url = https://github.com/zhuzichu520/FluentUI.git 4 | 5 | [submodule "protobuf"] 6 | path = protobuf 7 | url = https://github.com/zhuzichu520/protobuf.git 8 | 9 | [submodule "QxOrm"] 10 | path = QxOrm 11 | url = https://github.com/zhuzichu520/QxOrm.git -------------------------------------------------------------------------------- /3rdparty/Win_x64/mingw/libcrypto-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/mingw/libcrypto-1_1-x64.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/mingw/libgcc_s_seh-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/mingw/libgcc_s_seh-1.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/mingw/libssl-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/mingw/libssl-1_1-x64.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/mingw/libstdc++-6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/mingw/libstdc++-6.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/mingw/libwinpthread-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/mingw/libwinpthread-1.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/msvc/libcrypto-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/msvc/libcrypto-1_1-x64.dll -------------------------------------------------------------------------------- /3rdparty/Win_x64/msvc/libssl-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x64/msvc/libssl-1_1-x64.dll -------------------------------------------------------------------------------- /3rdparty/Win_x86/mingw/libcrypto-1_1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x86/mingw/libcrypto-1_1.dll -------------------------------------------------------------------------------- /3rdparty/Win_x86/mingw/libssl-1_1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x86/mingw/libssl-1_1.dll -------------------------------------------------------------------------------- /3rdparty/Win_x86/msvc/libcrypto-1_1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x86/msvc/libcrypto-1_1.dll -------------------------------------------------------------------------------- /3rdparty/Win_x86/msvc/libssl-1_1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/3rdparty/Win_x86/msvc/libssl-1_1.dll -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | project(kim VERSION 0.1 LANGUAGES CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | 7 | set(FLUENTUI_BUILD_EXAMPLES OFF) 8 | set(protobuf_BUILD_TESTS OFF) 9 | set(protobuf_BUILD_PROTOC_BINARIES OFF) 10 | set(protobuf_BUILD_SHARED_LIBS ON) 11 | set(protobuf_WITH_ZLIB OFF) 12 | 13 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 14 | set(KIM_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/debug) 15 | else() 16 | set(KIM_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/release) 17 | endif() 18 | 19 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick) 20 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick) 21 | 22 | add_subdirectory(src) 23 | add_subdirectory(FluentUI) 24 | 25 | add_subdirectory(protobuf) 26 | set_target_properties(libprotobuf PROPERTIES 27 | ARCHIVE_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 28 | LIBRARY_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 29 | RUNTIME_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 30 | ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 31 | LIBRARY_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 32 | RUNTIME_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 33 | ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 34 | LIBRARY_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 35 | RUNTIME_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 36 | ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 37 | LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 38 | RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 39 | ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 40 | LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 41 | RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 42 | ) 43 | 44 | add_subdirectory(QxOrm) 45 | target_compile_definitions(QxOrm PRIVATE 46 | -D_QX_NO_TRACE_DLL_ATTACH_DETACH 47 | -DQT_NO_STL 48 | ) 49 | set_target_properties(QxOrm PROPERTIES 50 | ARCHIVE_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 51 | LIBRARY_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 52 | RUNTIME_OUTPUT_DIRECTORY "${KIM_OUTPUT_DIRECTORY}" 53 | ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 54 | LIBRARY_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 55 | RUNTIME_OUTPUT_DIRECTORY_DEBUG "${KIM_OUTPUT_DIRECTORY}" 56 | ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 57 | LIBRARY_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 58 | RUNTIME_OUTPUT_DIRECTORY_RELEASE "${KIM_OUTPUT_DIRECTORY}" 59 | ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 60 | LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 61 | RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${KIM_OUTPUT_DIRECTORY}" 62 | ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 63 | LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 64 | RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${KIM_OUTPUT_DIRECTORY}" 65 | ) 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kim-qt 2 | 3 | [服务端链接](https://github.com/zhuzichu520/kim-boot-server) 4 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | project(kim VERSION 0.1 LANGUAGES CXX) 4 | 5 | set(CMAKE_AUTOUIC ON) 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 13 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${KIM_OUTPUT_DIRECTORY}) 14 | else() 15 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${KIM_OUTPUT_DIRECTORY}) 16 | endif() 17 | 18 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick WebSockets) 19 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick WebSockets) 20 | 21 | set(PROJECT_SOURCES 22 | qml.qrc 23 | main.cpp 24 | singleton.h 25 | stdafx.h 26 | db/export.h 27 | db/precompiled.h 28 | db/Message.h db/Message.cpp 29 | db/Session.h db/Session.cpp 30 | manager/IMManager.h manager/IMManager.cpp 31 | manager/DBManager.h manager/DBManager.cpp 32 | helper/SettingsHelper.h helper/SettingsHelper.cpp 33 | component/TextAreaDocument.h component/TextAreaDocument.cpp 34 | proto/Message.pb.h proto/Message.pb.cc 35 | proto/ReplyBody.pb.h proto/ReplyBody.pb.cc 36 | proto/SentBody.pb.h proto/SentBody.pb.cc 37 | controller/ContactController.h controller/ContactController.cpp 38 | model/ImageModel.h model/ImageModel.cpp 39 | model/UserModel.h model/UserModel.cpp 40 | model/BaseListModel.h 41 | model/SessionModel.h model/SessionModel.cpp 42 | model/MessageModel.h model/MessageModel.cpp 43 | model/EmoticonListModel.h model/EmoticonListModel.cpp 44 | model/MessageListModel.h model/MessageListModel.cpp 45 | model/SessionListModel.h model/SessionListModel.cpp 46 | model/ContactListModel.h model/ContactListModel.cpp 47 | provider/UserProvider.h provider/UserProvider.cpp 48 | component/CircularReveal.h component/CircularReveal.cpp 49 | helper/EmoticonHelper.h helper/EmoticonHelper.cpp 50 | event/MainEvent.h event/MainEvent.cpp 51 | ) 52 | 53 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) 54 | qt_add_executable(kim 55 | MANUAL_FINALIZATION 56 | ${PROJECT_SOURCES} 57 | ) 58 | # Define target properties for Android with Qt 6 as: 59 | # set_property(TARGET kim APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR 60 | # ${CMAKE_CURRENT_SOURCE_DIR}/android) 61 | # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation 62 | else() 63 | if(ANDROID) 64 | add_library(kim SHARED 65 | ${PROJECT_SOURCES} 66 | ) 67 | # Define properties for Android with Qt 5 after find_package() calls as: 68 | # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") 69 | else() 70 | add_executable(kim 71 | ${PROJECT_SOURCES} 72 | ) 73 | endif() 74 | endif() 75 | 76 | #获取文件路径分隔符(解决执行命令的时候有些平台会报错) 77 | file(TO_CMAKE_PATH "/" PATH_SEPARATOR) 78 | 79 | if(WIN32) 80 | #复制动态库到可执行文件同级目录下 81 | if(CMAKE_SIZEOF_VOID_P EQUAL 4) 82 | set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x86) 83 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) 84 | set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x64) 85 | endif() 86 | if(MSVC) 87 | set(DLLPATH ${3RDPARTY_ARCH_DIR}/msvc/*.dll) 88 | elseif(MINGW) 89 | set(DLLPATH ${3RDPARTY_ARCH_DIR}/mingw/*.dll) 90 | endif() 91 | string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}") 92 | file(GLOB DLL_FILES ${DLLPATH}) 93 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD 94 | COMMAND ${CMAKE_COMMAND} -E copy 95 | ${DLL_FILES} 96 | ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 97 | ) 98 | endif() 99 | 100 | target_link_libraries(kim PRIVATE 101 | Qt${QT_VERSION_MAJOR}::Core 102 | Qt${QT_VERSION_MAJOR}::Quick 103 | Qt${QT_VERSION_MAJOR}::WebSockets 104 | libprotobuf 105 | fluentuiplugin 106 | QxOrm 107 | ) 108 | 109 | target_compile_definitions(kim PRIVATE 110 | -D_BUILDING_QX_KIM 111 | ) 112 | 113 | set_target_properties(kim PROPERTIES 114 | MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com 115 | MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} 116 | MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} 117 | MACOSX_BUNDLE TRUE 118 | WIN32_EXECUTABLE TRUE 119 | ) 120 | 121 | target_include_directories(kim PRIVATE 122 | ${CMAKE_CURRENT_SOURCE_DIR} 123 | ${CMAKE_SOURCE_DIR}/QxOrm/include 124 | ) 125 | 126 | install(TARGETS kim 127 | BUNDLE DESTINATION . 128 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 129 | 130 | if(QT_VERSION_MAJOR EQUAL 6) 131 | qt_import_qml_plugins(kim) 132 | qt_finalize_executable(kim) 133 | endif() 134 | -------------------------------------------------------------------------------- /src/component/CircularReveal.cpp: -------------------------------------------------------------------------------- 1 | #include "CircularReveal.h" 2 | #include 3 | #include 4 | #include 5 | 6 | CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent) 7 | { 8 | setVisible(false); 9 | _anim.setDuration(333); 10 | _anim.setEasingCurve(QEasingCurve::OutCubic); 11 | connect(&_anim, &QPropertyAnimation::finished,this,[=](){ 12 | update(); 13 | setVisible(false); 14 | Q_EMIT animationFinished(); 15 | }); 16 | connect(this,&CircularReveal::radiusChanged,this,[=](){ 17 | update(); 18 | }); 19 | } 20 | 21 | void CircularReveal::paint(QPainter* painter) 22 | { 23 | painter->save(); 24 | painter->drawImage(QRect(0, 0, static_cast(width()), static_cast(height())), _source); 25 | QPainterPath path; 26 | path.moveTo(_center.x(),_center.y()); 27 | path.addEllipse(QPointF(_center.x(),_center.y()), _radius, _radius); 28 | painter->setCompositionMode(QPainter::CompositionMode_Clear); 29 | painter->fillPath(path, Qt::black); 30 | painter->restore(); 31 | } 32 | 33 | void CircularReveal::start(int w,int h,const QPoint& center,int radius){ 34 | _anim.setStartValue(0); 35 | _anim.setEndValue(radius); 36 | _center = center; 37 | _grabResult = _target->grabToImage(QSize(w,h)); 38 | connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult); 39 | } 40 | 41 | void CircularReveal::handleGrabResult(){ 42 | _grabResult.data()->image().swap(_source); 43 | update(); 44 | setVisible(true); 45 | Q_EMIT imageChanged(); 46 | _anim.start(); 47 | } 48 | -------------------------------------------------------------------------------- /src/component/CircularReveal.h: -------------------------------------------------------------------------------- 1 | #ifndef CIRCULARREVEAL_H 2 | #define CIRCULARREVEAL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class CircularReveal : public QQuickPaintedItem 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY_AUTO(QQuickItem*,target) 14 | Q_PROPERTY_AUTO(int,radius) 15 | public: 16 | CircularReveal(QQuickItem* parent = nullptr); 17 | void paint(QPainter* painter) override; 18 | Q_INVOKABLE void start(int w,int h,const QPoint& center,int radius); 19 | Q_SIGNAL void imageChanged(); 20 | Q_SIGNAL void animationFinished(); 21 | Q_SLOT void handleGrabResult(); 22 | private: 23 | QImage _source; 24 | QPropertyAnimation _anim = QPropertyAnimation(this, "radius", this); 25 | QPoint _center; 26 | QSharedPointer _grabResult; 27 | }; 28 | 29 | #endif // CIRCULARREVEAL_H 30 | -------------------------------------------------------------------------------- /src/component/TextAreaDocument.cpp: -------------------------------------------------------------------------------- 1 | #include "TextAreaDocument.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | TextAreaDocument::TextAreaDocument(QObject *parent) 13 | : QObject{parent} 14 | { 15 | _document = nullptr; 16 | } 17 | 18 | TextAreaDocument::~TextAreaDocument(){ 19 | 20 | } 21 | 22 | QTextDocument* TextAreaDocument::textDocument() const 23 | { 24 | if (_document) 25 | return _document->textDocument(); 26 | else return nullptr; 27 | } 28 | 29 | QTextCursor TextAreaDocument::textCursor() const 30 | { 31 | QTextDocument *doc = textDocument(); 32 | if (!doc) 33 | return QTextCursor(); 34 | QTextCursor cursor = QTextCursor(doc); 35 | if (_selectionStart != _selectionEnd) 36 | { 37 | cursor.setPosition(_selectionStart); 38 | cursor.setPosition(_selectionEnd, QTextCursor::KeepAnchor); 39 | } 40 | else 41 | { 42 | cursor.setPosition(_cursorPosition); 43 | } 44 | return cursor; 45 | } 46 | 47 | void TextAreaDocument::insertImage(const QString& url){ 48 | QTextImageFormat format; 49 | format.setName(url); 50 | format.setWidth(20); 51 | format.setHeight(20); 52 | textCursor().insertImage(format, QTextFrameFormat::InFlow); 53 | } 54 | 55 | QString TextAreaDocument::rawText(){ 56 | auto doc = textDocument(); 57 | return toRawText(0,doc->characterCount()-1); 58 | } 59 | 60 | QString TextAreaDocument::toRawText(int start,int end){ 61 | auto doc = textDocument(); 62 | QString text; 63 | QTextBlock block = doc->begin(); 64 | int index = 0; 65 | while (block.isValid()) { 66 | for (QTextBlock::iterator it = block.begin(); !it.atEnd(); ++it) { 67 | QTextFragment fragment = it.fragment(); 68 | QTextCharFormat format = fragment.charFormat(); 69 | if(format.isImageFormat()){ 70 | QTextImageFormat imageFormat = format.toImageFormat(); 71 | for (int var = 0; var < fragment.length(); var++) { 72 | if(index>=start && index < end){ 73 | text.append(EmoticonHelper::getInstance()->getTagByUrl(imageFormat.name())); 74 | } 75 | index++; 76 | } 77 | }else{ 78 | auto s = fragment.text(); 79 | for (int var = 0; var < fragment.length(); var++) { 80 | if(index>=start && index < end){ 81 | text.append(s.at(var)); 82 | } 83 | index++; 84 | } 85 | } 86 | } 87 | if(doc->lastBlock() != block){ 88 | text.append("\n"); 89 | } 90 | block = block.next(); 91 | } 92 | return text; 93 | } 94 | -------------------------------------------------------------------------------- /src/component/TextAreaDocument.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTAREADOCUMENT_H 2 | #define TEXTAREADOCUMENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class TextAreaDocument : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY_AUTO(QQuickTextDocument*,document) 12 | Q_PROPERTY_AUTO(int,cursorPosition) 13 | Q_PROPERTY_AUTO(int,selectionStart) 14 | Q_PROPERTY_AUTO(int,selectionEnd) 15 | Q_PROPERTY_AUTO(int,emoticonSize) 16 | public: 17 | explicit TextAreaDocument(QObject *parent = nullptr); 18 | ~TextAreaDocument(); 19 | QTextDocument *textDocument() const; 20 | QTextCursor textCursor() const; 21 | Q_INVOKABLE void insertImage(const QString& url); 22 | Q_INVOKABLE QString rawText(); 23 | Q_SIGNAL void insertTextChanged(QString text); 24 | QString toRawText(int start,int end); 25 | }; 26 | 27 | #endif // TEXTAREADOCUMENT_H 28 | -------------------------------------------------------------------------------- /src/controller/ContactController.cpp: -------------------------------------------------------------------------------- 1 | #include "ContactController.h" 2 | 3 | 4 | ContactController::ContactController(QObject *parent) 5 | : QObject{parent} { 6 | 7 | } 8 | 9 | 10 | ContactController::~ContactController() { 11 | 12 | } 13 | 14 | void ContactController::hadnleClickItemContact(const QString& uid){ 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/controller/ContactController.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTACTCONTROLLER_H 2 | #define CONTACTCONTROLLER_H 3 | 4 | #include 5 | 6 | class ContactController : public QObject 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit ContactController(QObject *parent = nullptr); 11 | ~ContactController() override; 12 | Q_INVOKABLE void hadnleClickItemContact(const QString& uid); 13 | 14 | }; 15 | 16 | #endif // CONTACTCONTROLLER_H 17 | -------------------------------------------------------------------------------- /src/db/Message.cpp: -------------------------------------------------------------------------------- 1 | #include "Message.h" 2 | 3 | #include 4 | 5 | QX_REGISTER_CPP_QX_KIM(Message) 6 | 7 | namespace qx { 8 | template<> void register_class(QxClass &t) 9 | { 10 | t.id(&Message::id, "id"); 11 | t.data(&Message::title, "title"); 12 | t.data(&Message::content, "content"); 13 | t.data(&Message::sender, "sender"); 14 | t.data(&Message::receiver, "receiver"); 15 | t.data(&Message::scene, "scene"); 16 | t.data(&Message::type, "type"); 17 | t.data(&Message::subType, "sub_type"); 18 | t.data(&Message::extra, "extra"); 19 | t.data(&Message::localExtra, "local_extra"); 20 | t.data(&Message::timestamp, "timestamp"); 21 | t.data(&Message::status, "status"); 22 | t.data(&Message::sessionId, "session_id"); 23 | t.data(&Message::readUidList, "read_uid_list"); 24 | } 25 | } 26 | 27 | Message::Message(){ 28 | 29 | } 30 | 31 | Message::~Message(){ 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/db/Message.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGE_H 2 | #define MESSAGE_H 3 | 4 | #include 5 | 6 | class QX_KIM_DLL_EXPORT Message { 7 | public: 8 | 9 | Message(); 10 | ~Message(); 11 | 12 | public: 13 | QString id; 14 | QString title; 15 | QString content; 16 | QString sender; 17 | QString receiver; 18 | int scene = 0; 19 | int type = 0; 20 | int subType = 0; 21 | QString extra; 22 | QString localExtra; 23 | qint64 timestamp = 0; 24 | int status = 0; 25 | QString sessionId; 26 | QString readUidList; 27 | }; 28 | 29 | QX_REGISTER_PRIMARY_KEY(Message, QString) 30 | QX_REGISTER_HPP_QX_KIM (Message, qx::trait::no_base_class_defined, 0) 31 | 32 | #endif // MESSAGE_H 33 | -------------------------------------------------------------------------------- /src/db/Session.cpp: -------------------------------------------------------------------------------- 1 | #include "Session.h" 2 | 3 | QX_REGISTER_CPP_QX_KIM(Session) 4 | 5 | namespace qx { 6 | template<> 7 | void register_class(QxClass &t) { 8 | t.id(&Session::id, "id"); 9 | t.data(&Session::content, "content"); 10 | t.data(&Session::scene, "scene"); 11 | t.data(&Session::type, "type"); 12 | t.data(&Session::subType, "sub_type"); 13 | t.data(&Session::extra, "extra"); 14 | t.data(&Session::timestamp, "timestamp"); 15 | t.data(&Session::unreadCount, "unread_count"); 16 | t.data(&Session::status, "status"); 17 | t.data(&Session::draft, "draft"); 18 | t.data(&Session::stayTop, "stay_top"); 19 | } 20 | } 21 | 22 | Session::Session(){ 23 | 24 | } 25 | 26 | Session::~Session(){ 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/db/Session.h: -------------------------------------------------------------------------------- 1 | #ifndef SESSION_H 2 | #define SESSION_H 3 | 4 | #include 5 | 6 | class QX_KIM_DLL_EXPORT Session { 7 | public: 8 | Session(); 9 | ~Session(); 10 | QString m_id; 11 | QString id; 12 | QString content; 13 | int scene = 0; 14 | int type = 0; 15 | int subType = 0; 16 | QString extra; 17 | qint64 timestamp =0; 18 | int unreadCount = 0; 19 | int status = 0; 20 | QString draft; 21 | bool stayTop = false; 22 | }; 23 | 24 | QX_REGISTER_PRIMARY_KEY(Session, QString) 25 | QX_REGISTER_HPP_QX_KIM (Session, qx::trait::no_base_class_defined, 0) 26 | 27 | #endif // SESSION_H 28 | -------------------------------------------------------------------------------- /src/db/export.h: -------------------------------------------------------------------------------- 1 | #ifndef _QX_KIM_EXPORT_H_ 2 | #define _QX_KIM_EXPORT_H_ 3 | 4 | #ifdef _BUILDING_QX_KIM 5 | #define QX_KIM_DLL_EXPORT QX_DLL_EXPORT_HELPER 6 | #else // _BUILDING_QX_KIM 7 | #define QX_KIM_DLL_EXPORT QX_DLL_IMPORT_HELPER 8 | #endif // _BUILDING_QX_KIM 9 | 10 | #ifdef _BUILDING_QX_KIM 11 | #define QX_REGISTER_HPP_QX_KIM QX_REGISTER_HPP_EXPORT_DLL 12 | #define QX_REGISTER_CPP_QX_KIM QX_REGISTER_CPP_EXPORT_DLL 13 | #else // _BUILDING_QX_KIM 14 | #define QX_REGISTER_HPP_QX_KIM QX_REGISTER_HPP_IMPORT_DLL 15 | #define QX_REGISTER_CPP_QX_KIM QX_REGISTER_CPP_IMPORT_DLL 16 | #endif // _BUILDING_QX_KIM 17 | 18 | #endif // _QX_KIM_EXPORT_H_ 19 | -------------------------------------------------------------------------------- /src/db/precompiled.h: -------------------------------------------------------------------------------- 1 | #ifndef _QX_KIM_PRECOMPILED_HEADER_H_ 2 | #define _QX_KIM_PRECOMPILED_HEADER_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #endif // _QX_KIM_PRECOMPILED_HEADER_H_ 9 | -------------------------------------------------------------------------------- /src/event/MainEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "MainEvent.h" 2 | 3 | #include 4 | #include 5 | 6 | MainEvent::MainEvent(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | MainEvent::~MainEvent() = default; 12 | -------------------------------------------------------------------------------- /src/event/MainEvent.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINEVENT_H 2 | #define MAINEVENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class MainEvent : public QObject 14 | { 15 | Q_OBJECT 16 | private: 17 | explicit MainEvent(QObject* parent = nullptr); 18 | public: 19 | SINGLETONG(MainEvent) 20 | ~MainEvent() override; 21 | Q_SIGNAL void switchSessionEvent(QString uid); 22 | }; 23 | 24 | #endif // MAINEVENT_H 25 | -------------------------------------------------------------------------------- /src/helper/EmoticonHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "EmoticonHelper.h" 2 | 3 | #include 4 | 5 | Emoticon::Emoticon(QObject *parent) 6 | : QObject{parent} 7 | { 8 | this->_file = "file"; 9 | this->_name = "name"; 10 | this->_tag = "tag"; 11 | } 12 | 13 | Emoticon::Emoticon(QString file,QString name,QString tag,QObject *parent) 14 | : QObject{parent} 15 | { 16 | this->_file = file; 17 | this->_name = name; 18 | this->_tag = tag; 19 | } 20 | 21 | QString EmoticonHelper::getFileByTag(const QString& tag){ 22 | foreach (auto item, _datas) { 23 | if(item->tag()==tag){ 24 | return item->file(); 25 | } 26 | } 27 | return ""; 28 | } 29 | 30 | QString EmoticonHelper::getTagByFile(const QString& file){ 31 | foreach (auto item, _datas) { 32 | if(item->file()==file){ 33 | return item->tag(); 34 | } 35 | } 36 | return ""; 37 | } 38 | 39 | QString EmoticonHelper::getTagByUrl(QString url){ 40 | return getTagByFile(url.replace(_prefix,"")); 41 | } 42 | 43 | EmoticonHelper::EmoticonHelper(QObject *parent) 44 | : QObject{parent} 45 | { 46 | _datas.append(QSharedPointer(new Emoticon("emoji_00.png","emoticon_emoji_0","[大笑]"))); 47 | _datas.append(QSharedPointer(new Emoticon("emoji_01.png","emoticon_emoji_01","[开心]"))); 48 | _datas.append(QSharedPointer(new Emoticon("emoji_02.png","emoticon_emoji_02","[色]"))); 49 | _datas.append(QSharedPointer(new Emoticon("emoji_03.png","emoticon_emoji_03","[酷]"))); 50 | _datas.append(QSharedPointer(new Emoticon("emoji_04.png","emoticon_emoji_04","[奸笑]"))); 51 | _datas.append(QSharedPointer(new Emoticon("emoji_05.png","emoticon_emoji_05","[亲]"))); 52 | _datas.append(QSharedPointer(new Emoticon("emoji_06.png","emoticon_emoji_06","[伸舌头]"))); 53 | _datas.append(QSharedPointer(new Emoticon("emoji_07.png","emoticon_emoji_07","[眯眼]"))); 54 | _datas.append(QSharedPointer(new Emoticon("emoji_08.png","emoticon_emoji_08","[可爱]"))); 55 | _datas.append(QSharedPointer(new Emoticon("emoji_09.png","emoticon_emoji_09","[鬼脸]"))); 56 | _datas.append(QSharedPointer(new Emoticon("emoji_10.png","emoticon_emoji_10","[偷笑]"))); 57 | _datas.append(QSharedPointer(new Emoticon("emoji_11.png","emoticon_emoji_11","[喜悦]"))); 58 | _datas.append(QSharedPointer(new Emoticon("emoji_12.png","emoticon_emoji_12","[狂喜]"))); 59 | _datas.append(QSharedPointer(new Emoticon("emoji_13.png","emoticon_emoji_13","[惊讶]"))); 60 | _datas.append(QSharedPointer(new Emoticon("emoji_14.png","emoticon_emoji_14","[流泪]"))); 61 | _datas.append(QSharedPointer(new Emoticon("emoji_15.png","emoticon_emoji_15","[流汗]"))); 62 | _datas.append(QSharedPointer(new Emoticon("emoji_16.png","emoticon_emoji_16","[天使]"))); 63 | _datas.append(QSharedPointer(new Emoticon("emoji_17.png","emoticon_emoji_17","[笑哭]"))); 64 | _datas.append(QSharedPointer(new Emoticon("emoji_18.png","emoticon_emoji_18","[尴尬]"))); 65 | _datas.append(QSharedPointer(new Emoticon("emoji_19.png","emoticon_emoji_19","[惊恐]"))); 66 | _datas.append(QSharedPointer(new Emoticon("emoji_20.png","emoticon_emoji_20","[大哭]"))); 67 | _datas.append(QSharedPointer(new Emoticon("emoji_21.png","emoticon_emoji_21","[烦躁]"))); 68 | _datas.append(QSharedPointer(new Emoticon("emoji_22.png","emoticon_emoji_22","[恐怖]"))); 69 | _datas.append(QSharedPointer(new Emoticon("emoji_23.png","emoticon_emoji_23","[两眼冒星]"))); 70 | _datas.append(QSharedPointer(new Emoticon("emoji_24.png","emoticon_emoji_24","[害羞]"))); 71 | _datas.append(QSharedPointer(new Emoticon("emoji_25.png","emoticon_emoji_25","[睡着]"))); 72 | _datas.append(QSharedPointer(new Emoticon("emoji_26.png","emoticon_emoji_26","[冒星]"))); 73 | _datas.append(QSharedPointer(new Emoticon("emoji_27.png","emoticon_emoji_27","[口罩]"))); 74 | _datas.append(QSharedPointer(new Emoticon("emoji_28.png","emoticon_emoji_28","[OK]"))); 75 | _datas.append(QSharedPointer(new Emoticon("emoji_29.png","emoticon_emoji_29","[好吧]"))); 76 | _datas.append(QSharedPointer(new Emoticon("emoji_30.png","emoticon_emoji_30","[鄙视]"))); 77 | _datas.append(QSharedPointer(new Emoticon("emoji_31.png","emoticon_emoji_31","[难受]"))); 78 | _datas.append(QSharedPointer(new Emoticon("emoji_32.png","emoticon_emoji_32","[不屑]"))); 79 | _datas.append(QSharedPointer(new Emoticon("emoji_33.png","emoticon_emoji_33","[不舒服]"))); 80 | _datas.append(QSharedPointer(new Emoticon("emoji_34.png","emoticon_emoji_34","[愤怒]"))); 81 | _datas.append(QSharedPointer(new Emoticon("emoji_35.png","emoticon_emoji_35","[鬼怪]"))); 82 | _datas.append(QSharedPointer(new Emoticon("emoji_36.png","emoticon_emoji_36","[发怒]"))); 83 | _datas.append(QSharedPointer(new Emoticon("emoji_37.png","emoticon_emoji_37","[生气]"))); 84 | _datas.append(QSharedPointer(new Emoticon("emoji_38.png","emoticon_emoji_38","[不高兴]"))); 85 | _datas.append(QSharedPointer(new Emoticon("emoji_39.png","emoticon_emoji_39","[皱眉]"))); 86 | _datas.append(QSharedPointer(new Emoticon("emoji_40.png","emoticon_emoji_40","[心碎]"))); 87 | _datas.append(QSharedPointer(new Emoticon("emoji_41.png","emoticon_emoji_41","[心动]"))); 88 | _datas.append(QSharedPointer(new Emoticon("emoji_42.png","emoticon_emoji_42","[好的]"))); 89 | _datas.append(QSharedPointer(new Emoticon("emoji_43.png","emoticon_emoji_43","[低级]"))); 90 | _datas.append(QSharedPointer(new Emoticon("emoji_44.png","emoticon_emoji_44","[赞]"))); 91 | _datas.append(QSharedPointer(new Emoticon("emoji_45.png","emoticon_emoji_45","[鼓掌]"))); 92 | _datas.append(QSharedPointer(new Emoticon("emoji_46.png","emoticon_emoji_46","[给力]"))); 93 | _datas.append(QSharedPointer(new Emoticon("emoji_47.png","emoticon_emoji_47","[打你]"))); 94 | _datas.append(QSharedPointer(new Emoticon("emoji_48.png","emoticon_emoji_48","[阿弥陀佛]"))); 95 | _datas.append(QSharedPointer(new Emoticon("emoji_49.png","emoticon_emoji_49","[拜拜]"))); 96 | _datas.append(QSharedPointer(new Emoticon("emoji_50.png","emoticon_emoji_50","[第一]"))); 97 | _datas.append(QSharedPointer(new Emoticon("emoji_51.png","emoticon_emoji_51","[拳头]"))); 98 | _datas.append(QSharedPointer(new Emoticon("emoji_52.png","emoticon_emoji_52","[手掌]"))); 99 | _datas.append(QSharedPointer(new Emoticon("emoji_53.png","emoticon_emoji_53","[剪刀]"))); 100 | _datas.append(QSharedPointer(new Emoticon("emoji_54.png","emoticon_emoji_54","[招手]"))); 101 | _datas.append(QSharedPointer(new Emoticon("emoji_55.png","emoticon_emoji_55","[不要]"))); 102 | _datas.append(QSharedPointer(new Emoticon("emoji_56.png","emoticon_emoji_56","[举着]"))); 103 | _datas.append(QSharedPointer(new Emoticon("emoji_57.png","emoticon_emoji_57","[思考]"))); 104 | _datas.append(QSharedPointer(new Emoticon("emoji_58.png","emoticon_emoji_58","[猪头]"))); 105 | _datas.append(QSharedPointer(new Emoticon("emoji_59.png","emoticon_emoji_59","[不听]"))); 106 | _datas.append(QSharedPointer(new Emoticon("emoji_60.png","emoticon_emoji_60","[不看]"))); 107 | _datas.append(QSharedPointer(new Emoticon("emoji_61.png","emoticon_emoji_61","[不说]"))); 108 | _datas.append(QSharedPointer(new Emoticon("emoji_62.png","emoticon_emoji_62","[猴子]"))); 109 | _datas.append(QSharedPointer(new Emoticon("emoji_63.png","emoticon_emoji_63","[炸弹]"))); 110 | _datas.append(QSharedPointer(new Emoticon("emoji_64.png","emoticon_emoji_64","[睡觉]"))); 111 | _datas.append(QSharedPointer(new Emoticon("emoji_65.png","emoticon_emoji_65","[筋斗云]"))); 112 | _datas.append(QSharedPointer(new Emoticon("emoji_66.png","emoticon_emoji_66","[火箭]"))); 113 | _datas.append(QSharedPointer(new Emoticon("emoji_67.png","emoticon_emoji_67","[救护车]"))); 114 | _datas.append(QSharedPointer(new Emoticon("emoji_68.png","emoticon_emoji_68","[便便]"))); 115 | QList tags; 116 | foreach (auto item, _datas) { 117 | tags.append(item.get()->tag()); 118 | } 119 | QString tagPattern = "("+ tags.join("|") + ")"; 120 | _tagRegular.setPattern(tagPattern.replace("[","\\[").replace("]","\\]")); 121 | } 122 | 123 | QString EmoticonHelper::toEmoticonString(QString text,int size){ 124 | QRegularExpressionMatchIterator it = EmoticonHelper::getInstance()->_tagRegular.globalMatch(text); 125 | int offset = 0; 126 | while (it.hasNext ()) { 127 | QRegularExpressionMatch match = it.next(); 128 | int length = match.capturedLength (); 129 | int begin = match.capturedStart () + offset; 130 | QString tag = match.captured(1); 131 | QString replaceString = QString::fromStdString("\"%3\"/").arg((_prefix + getFileByTag(tag)),QString::number(size),tag); 132 | text.replace(begin,length,replaceString); 133 | offset += replaceString.length() - length; 134 | } 135 | return QString::fromStdString("
%1
").arg(text); 136 | } 137 | 138 | -------------------------------------------------------------------------------- /src/helper/EmoticonHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef EMOTICONHELPER_H 2 | #define EMOTICONHELPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Emoticon : public QObject 12 | { 13 | Q_OBJECT 14 | Q_PROPERTY_AUTO(QString,file); 15 | Q_PROPERTY_AUTO(QString,name); 16 | Q_PROPERTY_AUTO(QString,tag); 17 | public: 18 | explicit Emoticon(QObject *parent = nullptr); 19 | Emoticon(QString file,QString name,QString tag,QObject *parent = nullptr); 20 | 21 | }; 22 | 23 | class EmoticonHelper : public QObject 24 | { 25 | Q_OBJECT 26 | public: 27 | SINGLETONG(EmoticonHelper) 28 | explicit EmoticonHelper(QObject *parent = nullptr); 29 | 30 | QList> _datas; 31 | QString getFileByTag(const QString& tag); 32 | QString getTagByFile(const QString& file); 33 | QString getTagByUrl(QString url); 34 | void addResource(QTextDocument* textDocument); 35 | Q_INVOKABLE QString toEmoticonString(QString text,int size = 20); 36 | public: 37 | QRegularExpression _tagRegular; 38 | QString _prefix = "qrc:/res/image/emoji/"; 39 | QString _prefix_emoji = "emoji:/"; 40 | }; 41 | 42 | #endif // EMOTICONHELPER_H 43 | -------------------------------------------------------------------------------- /src/helper/SettingsHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "SettingsHelper.h" 2 | 3 | #include 4 | #include 5 | 6 | SettingsHelper::SettingsHelper(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | SettingsHelper::~SettingsHelper() = default; 12 | 13 | void SettingsHelper::save(const QString& key,QVariant val) 14 | { 15 | QByteArray data = {}; 16 | QDataStream stream(&data, QIODevice::WriteOnly); 17 | stream.setVersion(QDataStream::Qt_5_6); 18 | stream << val; 19 | m_settings->setValue(key, data); 20 | } 21 | 22 | QVariant SettingsHelper::get(const QString& key,QVariant def){ 23 | const QByteArray data = m_settings->value(key).toByteArray(); 24 | if (data.isEmpty()) { 25 | return def; 26 | } 27 | QDataStream stream(data); 28 | stream.setVersion(QDataStream::Qt_5_6); 29 | QVariant val; 30 | stream >> val; 31 | return val; 32 | } 33 | 34 | void SettingsHelper::init(char *argv[]){ 35 | auto applicationPath = QString::fromStdString(argv[0]); 36 | const QFileInfo fileInfo(applicationPath); 37 | const QString iniFileName = fileInfo.completeBaseName() + ".ini"; 38 | const QString iniFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + iniFileName; 39 | qDebug()<<"Application configuration file path->"< 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class SettingsHelper : public QObject 14 | { 15 | Q_OBJECT 16 | private: 17 | explicit SettingsHelper(QObject* parent = nullptr); 18 | public: 19 | SINGLETONG(SettingsHelper) 20 | ~SettingsHelper() override; 21 | void init(char *argv[]); 22 | void saveToken(const QVariant& token){save("token",token);} 23 | Q_INVOKABLE QVariant getToken(){return get("token");} 24 | 25 | void saveAccount(const QVariant& account){save("account",account);} 26 | Q_INVOKABLE QVariant getAccount(){return get("account");} 27 | 28 | void saveLastSyncMessageTimestamp(const QVariant& timestamp){save("last_sync_message_timestamp",timestamp);} 29 | Q_INVOKABLE QVariant getLastSyncMessageTimestamp(){return get("last_sync_message_timestamp");} 30 | 31 | Q_INVOKABLE void login(const QString& account,const QString& token){ 32 | saveAccount(account); 33 | saveToken(token); 34 | } 35 | Q_INVOKABLE void logout(){ 36 | saveAccount(""); 37 | saveToken(""); 38 | } 39 | Q_INVOKABLE bool isLogin(){ 40 | return !getAccount().toString().isEmpty(); 41 | } 42 | 43 | 44 | private: 45 | void save(const QString& key,QVariant val); 46 | QVariant get(const QString& key,QVariant def={}); 47 | private: 48 | QScopedPointer m_settings; 49 | }; 50 | 51 | #endif // SETTINGSHELPER_H 52 | -------------------------------------------------------------------------------- /src/helper/TextDocumentHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "TextDocumentHelper.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | TextDocumentHelper::TextDocumentHelper(QObject *parent) 13 | : QObject{parent} 14 | { 15 | _document = nullptr; 16 | } 17 | 18 | TextDocumentHelper::~TextDocumentHelper(){ 19 | 20 | } 21 | 22 | QTextDocument* TextDocumentHelper::textDocument() const 23 | { 24 | if (_document) 25 | return _document->textDocument(); 26 | else return nullptr; 27 | } 28 | 29 | QTextCursor TextDocumentHelper::textCursor() const 30 | { 31 | QTextDocument *doc = textDocument(); 32 | if (!doc) 33 | return QTextCursor(); 34 | QTextCursor cursor = QTextCursor(doc); 35 | if (_selectionStart != _selectionEnd) 36 | { 37 | cursor.setPosition(_selectionStart); 38 | cursor.setPosition(_selectionEnd, QTextCursor::KeepAnchor); 39 | } 40 | else 41 | { 42 | cursor.setPosition(_cursorPosition); 43 | } 44 | return cursor; 45 | } 46 | 47 | void TextDocumentHelper::insertImage(const QString& url){ 48 | QTextImageFormat format; 49 | format.setName(url); 50 | format.setWidth(20); 51 | format.setHeight(20); 52 | textCursor().insertImage(format, QTextFrameFormat::InFlow); 53 | } 54 | 55 | QString TextDocumentHelper::rawText(){ 56 | auto doc = textDocument(); 57 | return toRawText(0,doc->characterCount()-1); 58 | } 59 | 60 | QString TextDocumentHelper::toRawText(int start,int end){ 61 | auto doc = textDocument(); 62 | QString text; 63 | QTextBlock block = doc->begin(); 64 | int index = 0; 65 | while (block.isValid()) { 66 | for (QTextBlock::iterator it = block.begin(); !it.atEnd(); ++it) { 67 | QTextFragment fragment = it.fragment(); 68 | QTextCharFormat format = fragment.charFormat(); 69 | if(format.isImageFormat()){ 70 | QTextImageFormat imageFormat = format.toImageFormat(); 71 | for (int var = 0; var < fragment.length(); var++) { 72 | if(index>=start && index < end){ 73 | text.append(EmoticonHelper::getInstance()->getTagByUrl(imageFormat.name())); 74 | } 75 | index++; 76 | } 77 | }else{ 78 | auto s = fragment.text(); 79 | for (int var = 0; var < fragment.length(); var++) { 80 | if(index>=start && index < end){ 81 | text.append(s.at(var)); 82 | } 83 | index++; 84 | } 85 | } 86 | } 87 | if(doc->lastBlock() != block){ 88 | text.append("\n"); 89 | } 90 | block = block.next(); 91 | } 92 | return text; 93 | } 94 | -------------------------------------------------------------------------------- /src/helper/TextDocumentHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTDOCUMENTHELPER_H 2 | #define TEXTDOCUMENTHELPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class TextDocumentHelper : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY_AUTO(QQuickTextDocument*,document) 12 | Q_PROPERTY_AUTO(int,cursorPosition) 13 | Q_PROPERTY_AUTO(int,selectionStart) 14 | Q_PROPERTY_AUTO(int,selectionEnd) 15 | Q_PROPERTY_AUTO(int,emoticonSize) 16 | public: 17 | explicit TextDocumentHelper(QObject *parent = nullptr); 18 | ~TextDocumentHelper(); 19 | QTextDocument *textDocument() const; 20 | QTextCursor textCursor() const; 21 | Q_INVOKABLE void insertImage(const QString& url); 22 | Q_INVOKABLE QString rawText(); 23 | Q_SIGNAL void insertTextChanged(QString text); 24 | QString toRawText(int start,int end); 25 | }; 26 | 27 | #endif // TEXTDOCUMENTHELPER_H 28 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); 27 | #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) 28 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 29 | QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 30 | #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 31 | QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); 32 | #endif 33 | #endif 34 | qputenv("QT_QUICK_CONTROLS_STYLE","Basic"); 35 | QGuiApplication::setOrganizationName("ZhuZiChu"); 36 | QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io"); 37 | QGuiApplication::setApplicationName("KIM"); 38 | SettingsHelper::getInstance()->init(argv); 39 | QGuiApplication app(argc, argv); 40 | QQmlApplicationEngine engine; 41 | engine.rootContext()->setContextProperty("IMManager",IMManager::getInstance()); 42 | engine.rootContext()->setContextProperty("DBManager",DBManager::getInstance()); 43 | engine.rootContext()->setContextProperty("UserProvider",UserProvider::getInstance()); 44 | engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance()); 45 | engine.rootContext()->setContextProperty("EmoticonHelper",EmoticonHelper::getInstance()); 46 | engine.rootContext()->setContextProperty("MainEvent",MainEvent::getInstance()); 47 | qmlRegisterType("IM", 1, 0, "IMCallback"); 48 | qmlRegisterType("IM", 1, 0, "MessageListModel"); 49 | qmlRegisterType("IM", 1, 0, "EmoticonListModel"); 50 | qmlRegisterType("IM", 1, 0, "MessageListSortProxyModel"); 51 | qmlRegisterType("IM", 1, 0, "SessionListModel"); 52 | qmlRegisterType("IM", 1, 0, "SessionListSortProxyModel"); 53 | qmlRegisterType("IM", 1, 0, "ContactListModel"); 54 | qmlRegisterType("IM", 1, 0, "SessionModel"); 55 | qmlRegisterType("IM", 1, 0, "ImageModel"); 56 | qmlRegisterType("IM", 1, 0, "UserModel"); 57 | qmlRegisterType("IM", 1, 0, "Emoticon"); 58 | qmlRegisterType("IM", 1, 0, "CircularReveal"); 59 | qmlRegisterType("IM", 1, 0, "TextAreaDocument"); 60 | const QUrl url(QStringLiteral("qrc:/res/qml/App.qml")); 61 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 62 | &app, [url](QObject *obj, const QUrl &objUrl) { 63 | if (!obj && url == objUrl) 64 | QCoreApplication::exit(-1); 65 | }, Qt::QueuedConnection); 66 | engine.load(url); 67 | const int exec = QGuiApplication::exec(); 68 | if (exec == 931) { 69 | QProcess::startDetached(qApp->applicationFilePath(), QStringList()); 70 | } 71 | return exec; 72 | } 73 | -------------------------------------------------------------------------------- /src/manager/DBManager.cpp: -------------------------------------------------------------------------------- 1 | #include "DBManager.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | DBManager::DBManager(QObject *parent) 11 | : QObject{parent} 12 | { 13 | QDir dbDir(_dbPath); 14 | if(!dbDir.exists()){ 15 | dbDir.mkpath(dbDir.absolutePath()); 16 | } 17 | } 18 | 19 | DBManager::~DBManager(){ 20 | 21 | } 22 | 23 | void DBManager::initDb(){ 24 | if(_inited){ 25 | return; 26 | } 27 | auto account = SettingsHelper::getInstance()->getAccount().toString(); 28 | auto dbName = QString(QCryptographicHash::hash(account.toUtf8(), QCryptographicHash::Md5).toHex()); 29 | auto db=qx::QxSqlDatabase::getSingleton(); 30 | db->setDriverName("QSQLITE"); 31 | db->setDatabaseName(QString::fromStdString("%1/%2").arg(_dbPath,dbName)); 32 | db->setHostName("localhost"); 33 | db->setUserName("root"); 34 | db->setPassword(""); 35 | 36 | db->setFormatSqlQueryBeforeLogging(false); 37 | db->setDisplayTimerDetails(false); 38 | db->setVerifyOffsetRelation(true); 39 | db->setTraceSqlQuery(false); 40 | db->setTraceSqlBoundValues(false); 41 | db->setTraceSqlBoundValuesOnError(false); 42 | db->setTraceSqlRecord(false); 43 | 44 | QSqlError sqlError = qx::dao::create_table(); 45 | if(sqlError.isValid()){ 46 | qDebug()<(); 49 | if(sqlError.isValid()){ 50 | qDebug()< DBManager::findMessageByPage(QString sessionId,qint64 anchor,int pageSize){ 68 | qx::QxSqlQuery query(QString("WHERE Message.session_id = '%1' and Message.timestamp < %2 order by Message.timestamp desc limit %3").arg(sessionId).arg(anchor).arg(pageSize)); 69 | QList list; 70 | qx::dao::fetch_by_query(query, list); 71 | return list; 72 | } 73 | 74 | QList DBManager::findSessionListById(QString id){ 75 | qx::QxSqlQuery query(QString("WHERE Session.id = '%1'").arg(id)); 76 | QList list; 77 | qx::dao::fetch_by_query(query, list); 78 | return list; 79 | } 80 | 81 | QList DBManager::findMessageListBySessionId(QString sessionId){ 82 | qx::QxSqlQuery query(QString("WHERE Message.session_id = '%1'").arg(sessionId)); 83 | QList list; 84 | qx::dao::fetch_by_query(query, list); 85 | return list; 86 | } 87 | 88 | QList DBManager::findMessageListById(QString id){ 89 | qx::QxSqlQuery query(QString("WHERE Message.id = '%1'").arg(id)); 90 | QList list; 91 | qx::dao::fetch_by_query(query, list); 92 | return list; 93 | } 94 | 95 | QList DBManager::findLastMessage(){ 96 | qx::QxSqlQuery query(QString("WHERE Message.timestamp = (SELECT max(Message.timestamp) from Message)")); 97 | QList list; 98 | qx::dao::fetch_by_query(query, list); 99 | return list; 100 | } 101 | 102 | QList DBManager::findUnreadMessageList(const QString &sessionId,const QString &uid){ 103 | qx::QxSqlQuery query(QString("where session_id = '%1' and receiver = '%2'").arg(sessionId,uid)); 104 | QList list; 105 | qx::dao::fetch_by_query(query, list); 106 | QList data; 107 | for (int i = 0; i < list.size(); ++i) { 108 | auto &item = const_cast(list.at(i)); 109 | if (!item.readUidList.contains(uid)) { 110 | data.append(item); 111 | } 112 | } 113 | return data; 114 | } 115 | 116 | QList DBManager::findMessageByStatus(int status){ 117 | qx::QxSqlQuery query(QString("WHERE Message.status = '%1'").arg(status)); 118 | QList list; 119 | qx::dao::fetch_by_query(query, list); 120 | return list; 121 | } 122 | 123 | QList DBManager::findSessionAll(){ 124 | QList list; 125 | qx::dao::fetch_all(list); 126 | return list; 127 | } 128 | -------------------------------------------------------------------------------- /src/manager/DBManager.h: -------------------------------------------------------------------------------- 1 | #ifndef DBMANAGER_H 2 | #define DBMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class DBManager : public QObject 11 | { 12 | Q_OBJECT 13 | private: 14 | private: 15 | explicit DBManager(QObject *parent = nullptr); 16 | ~DBManager(); 17 | public: 18 | SINGLETONG(DBManager) 19 | void initDb(); 20 | bool saveOrUpdateMessage(Message message); 21 | QList findSessionListById(QString id); 22 | bool saveOrUpdateSession(Session session); 23 | QList findSessionAll(); 24 | QList findMessageListBySessionId(QString sessionId); 25 | QList findMessageListById(QString id); 26 | QList findUnreadMessageList(const QString &sessionId,const QString &uid); 27 | QList findLastMessage(); 28 | QList findMessageByStatus(int status); 29 | QList findMessageByPage(QString sessionId,qint64 anchor,int pageSize); 30 | bool deleteMessage(Message message); 31 | 32 | private: 33 | QString _dbPath = (QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/db"); 34 | bool _inited = false; 35 | }; 36 | 37 | #endif // DBMANAGER_H 38 | -------------------------------------------------------------------------------- /src/manager/IMManager.h: -------------------------------------------------------------------------------- 1 | #ifndef IMMANAGER_H 2 | #define IMMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class IMCallback: public QObject{ 17 | Q_OBJECT 18 | public: 19 | explicit IMCallback(QObject *parent = nullptr){}; 20 | ~IMCallback(){}; 21 | Q_SIGNAL void start(); 22 | Q_SIGNAL void finish(); 23 | Q_SIGNAL void success(QJsonObject result); 24 | Q_SIGNAL void error(int code,QString message); 25 | }; 26 | 27 | class IMManager : public QObject 28 | { 29 | Q_OBJECT 30 | Q_PROPERTY_AUTO(int,netStatus) 31 | Q_PROPERTY_AUTO(int,syncDataStatus) 32 | Q_PROPERTY_AUTO(QString,host) 33 | Q_PROPERTY_AUTO(QString,port) 34 | Q_PROPERTY_AUTO(QString,wsport) 35 | private: 36 | explicit IMManager(QObject *parent = nullptr); 37 | ~IMManager(); 38 | public: 39 | SINGLETONG(IMManager) 40 | Q_INVOKABLE void wsConnect(); 41 | Q_INVOKABLE void userRegister( 42 | const QString& account, 43 | const QString& password, 44 | const QString& confirmPassword, 45 | const QString& name, 46 | const QString& mobile, 47 | const QString& email, 48 | qint64 birthday, 49 | const QString& avatar, 50 | IMCallback* callback = nullptr 51 | ); 52 | Q_INVOKABLE void userLogin(const QString& account,const QString& password,IMCallback* callback = nullptr); 53 | Q_INVOKABLE void userSearch(const QString& keyword,IMCallback* callback = nullptr); 54 | Q_INVOKABLE void userProfile(IMCallback* callback = nullptr); 55 | Q_INVOKABLE void userInfo(const QString& account,IMCallback* callback = nullptr); 56 | Q_INVOKABLE void friendAdd(const QString& friendId,IMCallback* callback = nullptr); 57 | Q_INVOKABLE void friendRemove(const QString& friendId,IMCallback* callback = nullptr); 58 | Q_INVOKABLE void friends(IMCallback* callback = nullptr); 59 | Q_INVOKABLE void messageRead(const QString& ids,IMCallback* callback = nullptr); 60 | Q_INVOKABLE void resendMessage(const QString& id,IMCallback* callback); 61 | Q_INVOKABLE void sendTextMessage(const QString& receiver,const QString& text,IMCallback* callback,int scene=0); 62 | Q_INVOKABLE void addEmptySession(QString sessionId,int scene); 63 | Q_INVOKABLE void clearUnreadCount(const QString &sessionId); 64 | Q_INVOKABLE void sessionStayTop(const QString &sessionId,bool stayTop); 65 | Q_INVOKABLE void saveMessageDraft(const QString& sessionId,const QString& text); 66 | Q_INVOKABLE QString getMessageDraft(const QString& sessionId); 67 | Q_INVOKABLE void removeSession(const QString& sessionId); 68 | Q_SIGNAL void syncMessageCompleted(); 69 | Q_SIGNAL void messageChanged(QList data); 70 | Q_SIGNAL void sessionChanged(QList data); 71 | Q_SIGNAL void wsConnected(); 72 | Q_SLOT void onSocketMessage(const QByteArray &message); 73 | Q_INVOKABLE QString loginAccid(); 74 | Q_INVOKABLE QString token(); 75 | Q_INVOKABLE void openAutoRead(QString sessionId); 76 | QList getSessionList(); 77 | QList getMessageListBySessionId(QString sessionId); 78 | QList getMessageByPage(QString sessionId,qint64 anchor = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(),int pageSize=30); 79 | private: 80 | QString wsUri(); 81 | QString apiUri(); 82 | void bind(); 83 | void pong(); 84 | void post(const QString& path, QMap params,IMCallback* callback); 85 | void sendRequest(google::protobuf::Message* message); 86 | void sendMessage(Message message,IMCallback* callback); 87 | void sendMessageToLocal(Message& message); 88 | void updateSessionByMessage(const Message& message); 89 | void syncMessage(); 90 | void syncContacts(); 91 | void syncData(); 92 | void updateMessage(Message message); 93 | void updateSession(Session session); 94 | void handleFailedMessage(); 95 | Session message2session(const Message& val); 96 | Message json2message(const QString& login,const QJsonObject& val); 97 | Message buildMessage(const QString &sessionId, int scene, int type, const QString &content); 98 | private: 99 | QWebSocket* _socket = nullptr; 100 | QTimer _reconnectTimer; 101 | QString _autoReadSessionId = ""; 102 | }; 103 | 104 | #endif // IMMANAGER_H 105 | -------------------------------------------------------------------------------- /src/model/BaseListModel.h: -------------------------------------------------------------------------------- 1 | #ifndef BASELISTMODEL_H 2 | #define BASELISTMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | class BaseListModel : public QAbstractListModel 10 | { 11 | public: 12 | explicit BaseListModel(QObject *parent = nullptr){}; 13 | 14 | int rowCount(const QModelIndex &parent = QModelIndex()) const override{ 15 | Q_UNUSED(parent); 16 | return _datas.count(); 17 | } 18 | 19 | QVariant data(const QModelIndex &index, int role =Qt::DisplayRole) const override{ 20 | if (index.row() < 0 || index.row() >= _datas.count()) 21 | return {}; 22 | switch (role) { 23 | case Qt::DisplayRole: 24 | return QVariant::fromValue(_datas.at(index.row()).get()); 25 | default: 26 | break; 27 | } 28 | return QVariant(); 29 | } 30 | 31 | QHash roleNames() const override{ 32 | return { {Qt::DisplayRole, "display"} }; 33 | } 34 | 35 | QList> _datas; 36 | }; 37 | 38 | #endif // BASELISTMODEL_H 39 | -------------------------------------------------------------------------------- /src/model/ContactListModel.cpp: -------------------------------------------------------------------------------- 1 | #include "ContactListModel.h" 2 | 3 | #include 4 | #include 5 | 6 | ContactListModel::ContactListModel(QObject *parent) 7 | : BaseListModel{parent} 8 | { 9 | 10 | } 11 | 12 | ContactListModel::~ContactListModel(){ 13 | 14 | } 15 | 16 | QSharedPointer ContactListModel::handleFriend(QJsonObject val){ 17 | QSharedPointer userModel = QSharedPointer(new UserModel()); 18 | userModel->id(val.value("id").toString()); 19 | userModel->uid(val.value("uid").toString()); 20 | userModel->name(val.value("name").toString()); 21 | userModel->avatar(val.value("avatar").toString()); 22 | userModel->signature(val.value("signature").toString()); 23 | userModel->email(val.value("email").toString()); 24 | userModel->mobile(val.value("mobile").toString()); 25 | userModel->birthday(val.value("birthday").toDouble()); 26 | userModel->gender(val.value("gender").toInt()); 27 | userModel->extension(val.value("extension").toString()); 28 | return userModel; 29 | } 30 | 31 | void ContactListModel::resetData(){ 32 | IMCallback* callback = new IMCallback(this); 33 | connect(callback,&IMCallback::finish,this,[callback](){callback->deleteLater();}); 34 | connect(callback,&IMCallback::success,this,[callback,this](QJsonObject result){ 35 | beginResetModel(); 36 | _datas.clear(); 37 | if(result.contains("data")){ 38 | QJsonArray arr = result.value("data").toArray(); 39 | QList> data; 40 | foreach (auto item, arr) { 41 | data.append(handleFriend(item.toObject())); 42 | } 43 | _datas.append(data); 44 | } 45 | endResetModel(); 46 | }); 47 | IMManager::getInstance()->friends(callback); 48 | } 49 | 50 | void ContactListModel::clear(){ 51 | beginResetModel(); 52 | _datas.clear(); 53 | endResetModel(); 54 | } 55 | -------------------------------------------------------------------------------- /src/model/ContactListModel.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTACTLISTMODEL_H 2 | #define CONTACTLISTMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ContactListModel : public BaseListModel 10 | { 11 | Q_OBJECT 12 | public: 13 | 14 | explicit ContactListModel(QObject *parent = nullptr); 15 | ~ContactListModel(); 16 | 17 | Q_INVOKABLE void resetData(); 18 | Q_INVOKABLE void clear(); 19 | private: 20 | QSharedPointer handleFriend(QJsonObject val); 21 | 22 | }; 23 | 24 | #endif // CONTACTLISTMODEL_H 25 | -------------------------------------------------------------------------------- /src/model/EmoticonListModel.cpp: -------------------------------------------------------------------------------- 1 | #include "EmoticonListModel.h" 2 | 3 | EmoticonListModel::EmoticonListModel(QObject *parent) 4 | : BaseListModel{parent} 5 | { 6 | resetData(); 7 | } 8 | 9 | void EmoticonListModel::resetData(){ 10 | beginResetModel(); 11 | _datas = EmoticonHelper::getInstance()->_datas; 12 | endResetModel(); 13 | } 14 | -------------------------------------------------------------------------------- /src/model/EmoticonListModel.h: -------------------------------------------------------------------------------- 1 | #ifndef EMOTICONLISTMODEL_H 2 | #define EMOTICONLISTMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class EmoticonListModel : public BaseListModel 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit EmoticonListModel(QObject *parent = nullptr); 13 | 14 | void resetData(); 15 | 16 | }; 17 | 18 | #endif // EMOTICONLISTMODEL_H 19 | -------------------------------------------------------------------------------- /src/model/ImageModel.cpp: -------------------------------------------------------------------------------- 1 | #include "ImageModel.h" 2 | 3 | ImageModel::ImageModel(QObject *parent) 4 | : QObject{parent} 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/model/ImageModel.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEMODEL_H 2 | #define IMAGEMODEL_H 3 | 4 | #include 5 | #include 6 | 7 | class ImageModel : public QObject 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY_AUTO(QString,source) 11 | public: 12 | explicit ImageModel(QObject *parent = nullptr); 13 | QString url; 14 | }; 15 | 16 | #endif // IMAGEMODEL_H 17 | -------------------------------------------------------------------------------- /src/model/MessageListModel.cpp: -------------------------------------------------------------------------------- 1 | #include "MessageListModel.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | MessageListModel::MessageListModel(QObject *parent) 8 | : BaseListModel{parent} 9 | { 10 | _loadStatus = 0; 11 | _session = nullptr; 12 | connect(IMManager::getInstance(),&IMManager::messageChanged,this,[this](QList data){ 13 | for (int i = 0; i <= data.count()-1; ++i) { 14 | auto message = data.at(i); 15 | if(session()->id()==message.sessionId){ 16 | auto model = handleMessage(message); 17 | addOrUpdateData(model); 18 | } 19 | } 20 | }); 21 | } 22 | 23 | void MessageListModel::loadData(){ 24 | if(_loadStatus != 0){ 25 | return; 26 | } 27 | loadStatus(1); 28 | qint64 lastTimestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(); 29 | if(!_anchor.isNull()){ 30 | lastTimestamp = _anchor->timestamp(); 31 | } 32 | QList> data; 33 | auto list = IMManager::getInstance()->getMessageByPage(_session->id(),lastTimestamp,30); 34 | if(list.empty()){ 35 | Q_EMIT loadCompleted(); 36 | return; 37 | } 38 | foreach (auto item, list) { 39 | data.append(handleMessage(item)); 40 | } 41 | beginInsertRows(QModelIndex(), _datas.count(), _datas.count()+data.count()-1); 42 | _datas.append(data); 43 | endInsertRows(); 44 | loadStatus(0); 45 | if(data.count()<30){ 46 | loadStatus(2); 47 | } 48 | _anchor = data.last(); 49 | Q_EMIT loadCompleted(); 50 | } 51 | 52 | QSharedPointer MessageListModel::handleMessage(Message val){ 53 | auto model = QSharedPointer(new MessageModel(this)); 54 | auto loginAccid = IMManager::getInstance()->loginAccid(); 55 | model->id(val.id); 56 | model->content(val.content); 57 | model->sender(val.sender); 58 | model->receiver(val.receiver); 59 | model->scene(val.scene); 60 | model->type(val.type); 61 | model->subType(val.subType); 62 | model->extra(val.extra); 63 | model->localExtra(val.localExtra); 64 | model->timestamp(val.timestamp); 65 | model->status(val.status); 66 | model->sessionId(val.sessionId); 67 | model->readUidList(val.readUidList); 68 | model->isSelf(val.sender==loginAccid); 69 | model->user(model->isSelf() ? UserProvider::getInstance()->of(loginAccid) : UserProvider::getInstance()->of(val.sessionId)); 70 | model->body(QJsonDocument::fromJson(val.content.toUtf8()).object()); 71 | model->time(formatMessageTime(val.timestamp)); 72 | model->text(EmoticonHelper::getInstance()->toEmoticonString(model->body().value("msg").toString())); 73 | return model; 74 | } 75 | 76 | void MessageListModel::deleteMessage(int index){ 77 | beginRemoveRows(QModelIndex(), index, index); 78 | _datas.removeAt(index); 79 | endRemoveRows(); 80 | } 81 | 82 | QString MessageListModel::formatMessageTime(qint64 timestamp){ 83 | QDateTime dateTime; 84 | dateTime.setMSecsSinceEpoch(timestamp); 85 | QDateTime currentTime = QDateTime::currentDateTime(); 86 | qint64 days = dateTime.daysTo(currentTime); 87 | if (days == 0) { 88 | return dateTime.toString("hh:mm"); 89 | } else if(days ==1){ 90 | return dateTime.toString("昨天 hh:mm"); 91 | } { 92 | if (dateTime.date().year() == currentTime.date().year()) 93 | { 94 | return dateTime.toString("M月dd日 hh:mm"); 95 | } else 96 | { 97 | return dateTime.toString("yyyy年M月dd日 hh:mm"); 98 | } 99 | } 100 | } 101 | 102 | void MessageListModel::addOrUpdateData(QSharedPointer message){ 103 | for (int i = 0; i < _datas.size(); ++i) 104 | { 105 | auto item = _datas.at(i); 106 | if(item.get()->id() == message.get()->id()){ 107 | _datas.at(i)->setModel(message); 108 | Q_EMIT dataChanged(this->index(i,0),this->index(i,0)); 109 | return; 110 | } 111 | } 112 | beginInsertRows(QModelIndex(), 0, 0); 113 | _datas.insert(0,message); 114 | endInsertRows(); 115 | Q_EMIT viewToBottom(); 116 | } 117 | 118 | MessageListSortProxyModel::MessageListSortProxyModel(QSortFilterProxyModel *parent) 119 | : QSortFilterProxyModel {parent} 120 | { 121 | _model = nullptr; 122 | connect(this,&MessageListSortProxyModel::modelChanged,this,[=]{ 123 | setSourceModel(this->model()); 124 | sort(0, Qt::AscendingOrder); 125 | }); 126 | } 127 | 128 | bool MessageListSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{ 129 | return true; 130 | } 131 | 132 | bool MessageListSortProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const{ 133 | return true; 134 | } 135 | 136 | bool MessageListSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{ 137 | QSharedPointer left = _model->_datas.at(source_left.row()); 138 | QSharedPointer right = _model->_datas.at(source_right.row()); 139 | return left.get()->timestamp() > right.get()->timestamp(); 140 | } 141 | -------------------------------------------------------------------------------- /src/model/MessageListModel.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGELISTMODEL_H 2 | #define MESSAGELISTMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class MessageListModel : public BaseListModel 13 | { 14 | Q_OBJECT 15 | Q_PROPERTY_AUTO(SessionModel*,session) 16 | Q_PROPERTY_AUTO(int,loadStatus) 17 | public: 18 | explicit MessageListModel(QObject *parent = nullptr); 19 | Q_SIGNAL void viewToBottom(); 20 | Q_SIGNAL void viewToPosition(int position); 21 | Q_SIGNAL void loadCompleted(); 22 | Q_INVOKABLE void loadData(); 23 | Q_INVOKABLE void deleteMessage(int index); 24 | private: 25 | QSharedPointer handleMessage(Message val); 26 | void addOrUpdateData(QSharedPointer message); 27 | QString formatMessageTime(qint64 timestamp); 28 | private: 29 | QSharedPointer _anchor; 30 | }; 31 | 32 | class MessageListSortProxyModel : public QSortFilterProxyModel 33 | { 34 | Q_OBJECT 35 | Q_PROPERTY_AUTO(MessageListModel*,model) 36 | public: 37 | explicit MessageListSortProxyModel(QSortFilterProxyModel *parent = nullptr); 38 | 39 | bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; 40 | bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override; 41 | bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; 42 | }; 43 | 44 | 45 | #endif // MESSAGELISTMODEL_H 46 | -------------------------------------------------------------------------------- /src/model/MessageModel.cpp: -------------------------------------------------------------------------------- 1 | #include "MessageModel.h" 2 | 3 | MessageModel::MessageModel(QObject *parent) 4 | : QObject{parent} 5 | { 6 | 7 | } 8 | 9 | void MessageModel::setModel(QSharedPointer val){ 10 | auto message = val.get(); 11 | this->id(message->id()); 12 | this->content(message->content()); 13 | this->sender(message->sender()); 14 | this->receiver(message->receiver()); 15 | this->scene(message->scene()); 16 | this->type(message->type()); 17 | this->subType(message->subType()); 18 | this->extra(message->extra()); 19 | this->localExtra(message->localExtra()); 20 | this->timestamp(message->timestamp()); 21 | this->status(message->status()); 22 | this->sessionId(message->sessionId()); 23 | this->readUidList(message->readUidList()); 24 | 25 | this->isSelf(message->isSelf()); 26 | this->user(message->user()); 27 | this->body(message->body()); 28 | this->time(message->time()); 29 | this->text(message->text()); 30 | } 31 | -------------------------------------------------------------------------------- /src/model/MessageModel.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGEMODEL_H 2 | #define MESSAGEMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class MessageModel : public QObject 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY_AUTO(QString,id) 14 | Q_PROPERTY_AUTO(QString,content) 15 | Q_PROPERTY_AUTO(QString,sender) 16 | Q_PROPERTY_AUTO(QString,receiver) 17 | Q_PROPERTY_AUTO(int,scene) 18 | Q_PROPERTY_AUTO(int,type) 19 | Q_PROPERTY_AUTO(int,subType) 20 | Q_PROPERTY_AUTO(QString,extra) 21 | Q_PROPERTY_AUTO(QString,localExtra) 22 | Q_PROPERTY_AUTO(qint64,timestamp) 23 | Q_PROPERTY_AUTO(int,status) 24 | Q_PROPERTY_AUTO(QString,sessionId) 25 | Q_PROPERTY_AUTO(QString,readUidList) 26 | 27 | Q_PROPERTY_AUTO(bool,isSelf) 28 | Q_PROPERTY_AUTO(UserModel*,user) 29 | Q_PROPERTY_AUTO(QJsonObject,body) 30 | Q_PROPERTY_AUTO(QString,text) 31 | Q_PROPERTY_AUTO(QString,time) 32 | public: 33 | explicit MessageModel(QObject *parent = nullptr); 34 | void setModel(QSharedPointer val); 35 | }; 36 | 37 | #endif // MESSAGEMODEL_H 38 | -------------------------------------------------------------------------------- /src/model/SessionListModel.cpp: -------------------------------------------------------------------------------- 1 | #include "SessionListModel.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | SessionListModel::SessionListModel(QObject *parent) : BaseListModel(parent) { 8 | connect(IMManager::getInstance(),&IMManager::sessionChanged,this,[this](QList data){ 9 | for (int i = 0; i <= data.count()-1; ++i) { 10 | auto session = data.at(i); 11 | QSharedPointer sessionModel = handleSession(session); 12 | addOrUpdateData(sessionModel); 13 | } 14 | }); 15 | } 16 | 17 | SessionListModel::~SessionListModel(){ 18 | 19 | } 20 | 21 | void SessionListModel::addOrUpdateData(QSharedPointer session){ 22 | for (int i = 0; i < _datas.size(); ++i) 23 | { 24 | auto item = _datas.at(i); 25 | if(item.get()->id() == session.get()->id()){ 26 | _datas.at(i)->setModel(session); 27 | Q_EMIT dataChanged(this->index(i,0),this->index(i,0)); 28 | return; 29 | } 30 | } 31 | beginInsertRows(QModelIndex(), rowCount(), rowCount()); 32 | _datas.append(session); 33 | endInsertRows(); 34 | } 35 | 36 | void SessionListModel::resetData(){ 37 | beginResetModel(); 38 | _datas.clear(); 39 | QList> data; 40 | foreach (auto item, IMManager::getInstance()->getSessionList()) { 41 | data.append(handleSession(item)); 42 | } 43 | _datas.append(data); 44 | endResetModel(); 45 | } 46 | 47 | void SessionListModel::clear(){ 48 | beginResetModel(); 49 | _datas.clear(); 50 | endResetModel(); 51 | } 52 | 53 | QSharedPointer SessionListModel::handleSession(Session val){ 54 | auto model = QSharedPointer(new SessionModel(this)); 55 | model->id(val.id); 56 | model->content(val.content); 57 | model->scene(val.scene); 58 | model->type(val.type); 59 | model->subType(val.subType); 60 | model->extra(val.extra); 61 | model->timestamp(val.timestamp); 62 | model->unreadCount(val.unreadCount); 63 | model->status(val.status); 64 | model->stayTop(val.stayTop); 65 | model->draft(val.draft); 66 | model->user(UserProvider::getInstance()->of(val.id)); 67 | model->time(formatSessionime(val.timestamp)); 68 | if(!val.draft.isEmpty()){ 69 | model->text(handleDraft(val.draft)); 70 | }else{ 71 | model->text(handleContent(val.type,val.content)); 72 | } 73 | return model; 74 | } 75 | 76 | QString SessionListModel::formatSessionime(qint64 timestamp){ 77 | QDateTime dateTime; 78 | dateTime.setMSecsSinceEpoch(timestamp); 79 | QDateTime currentTime = QDateTime::currentDateTime(); 80 | qint64 days = dateTime.daysTo(currentTime); 81 | if (days == 0) { 82 | return dateTime.toString("hh:mm"); 83 | } else if(days ==1){ 84 | return dateTime.toString("昨天"); 85 | } { 86 | return dateTime.toString("yy/M/dd"); 87 | } 88 | } 89 | 90 | void SessionListModel::stayTopItem(const QString& id,bool stayTop){ 91 | IMManager::getInstance()->sessionStayTop(id,stayTop); 92 | } 93 | 94 | void SessionListModel::deleteItem(const QString& id){ 95 | int index = getIndexById(id); 96 | if(index!=-1){ 97 | beginRemoveRows(QModelIndex(),index,index); 98 | _datas.removeAt(index); 99 | endRemoveRows(); 100 | } 101 | } 102 | 103 | int SessionListModel::getIndexById(const QString& id){ 104 | int index = -1; 105 | for (int i = 0; i < _datas.size(); ++i) 106 | { 107 | auto item = _datas.at(i); 108 | if(item.get()->id() == id){ 109 | index = i; 110 | break; 111 | } 112 | } 113 | return index; 114 | } 115 | 116 | QString SessionListModel::handleDraft(const QString& draft){ 117 | return "[草稿]"+draft; 118 | } 119 | 120 | QString SessionListModel::handleContent(int type,const QString& content){ 121 | QJsonParseError error; 122 | auto jsonDocument = QJsonDocument::fromJson(content.toUtf8(),&error); 123 | if(error.error != QJsonParseError::NoError){ 124 | return "[未知消息]"; 125 | } 126 | auto object = jsonDocument.object(); 127 | switch(type){ 128 | case 0:{ 129 | auto msg = object["msg"].toString(); 130 | if(msg.length()>50){ 131 | msg = msg.mid(0,50); 132 | } 133 | return msg; 134 | } 135 | case 1: 136 | return "[图片]"; 137 | case 2: 138 | return "[文件]"; 139 | default: 140 | return "[未知消息]"; 141 | } 142 | } 143 | 144 | SessionModel* SessionListModel::getSessionByUid(const QString& uid){ 145 | for (int i = 0; i < _datas.size(); ++i) 146 | { 147 | auto item = _datas.at(i); 148 | if(item.get()->id() == uid){ 149 | return item.get(); 150 | } 151 | } 152 | return nullptr; 153 | } 154 | 155 | SessionListSortProxyModel::SessionListSortProxyModel(QSortFilterProxyModel *parent) 156 | : QSortFilterProxyModel {parent} 157 | { 158 | _model = nullptr; 159 | connect(this,&SessionListSortProxyModel::modelChanged,this,[=]{ 160 | setSourceModel(this->model()); 161 | sort(0, Qt::AscendingOrder); 162 | }); 163 | } 164 | 165 | bool SessionListSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{ 166 | return true; 167 | } 168 | 169 | bool SessionListSortProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const{ 170 | return true; 171 | } 172 | 173 | bool SessionListSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const{ 174 | QSharedPointer left = _model->_datas.at(source_left.row()); 175 | QSharedPointer right = _model->_datas.at(source_right.row()); 176 | if(left.get()->stayTop() && !right.get()->stayTop()){ 177 | return true; 178 | }else if(!left.get()->stayTop() && right.get()->stayTop()){ 179 | return false; 180 | }else{ 181 | return left.get()->timestamp()>right.get()->timestamp(); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/model/SessionListModel.h: -------------------------------------------------------------------------------- 1 | #ifndef SESSIONLISTMODEL_H 2 | #define SESSIONLISTMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class SessionListModel : public BaseListModel 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit SessionListModel(QObject *parent = nullptr); 17 | ~SessionListModel(); 18 | Q_INVOKABLE void resetData(); 19 | Q_INVOKABLE void clear(); 20 | Q_INVOKABLE SessionModel* getSessionByUid(const QString& uid); 21 | Q_INVOKABLE void stayTopItem(const QString& id,bool stayTop); 22 | Q_INVOKABLE void deleteItem(const QString& id); 23 | private: 24 | QSharedPointer handleSession(Session val); 25 | int getIndexById(const QString& id); 26 | QString handleContent(int type,const QString& content); 27 | QString handleDraft(const QString& draft); 28 | void addOrUpdateData(QSharedPointer session); 29 | QString formatSessionime(qint64 timestamp); 30 | }; 31 | 32 | class SessionListSortProxyModel : public QSortFilterProxyModel 33 | { 34 | Q_OBJECT 35 | Q_PROPERTY_AUTO(SessionListModel*,model) 36 | public: 37 | explicit SessionListSortProxyModel(QSortFilterProxyModel *parent = nullptr); 38 | 39 | bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; 40 | bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override; 41 | bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; 42 | }; 43 | 44 | #endif // SESSIONLISTMODEL_H 45 | -------------------------------------------------------------------------------- /src/model/SessionModel.cpp: -------------------------------------------------------------------------------- 1 | #include "SessionModel.h" 2 | 3 | #include 4 | 5 | SessionModel::SessionModel(QObject *parent) 6 | : QObject{parent} 7 | { 8 | 9 | } 10 | 11 | SessionModel::~SessionModel(){ 12 | 13 | } 14 | 15 | void SessionModel::setModel(QSharedPointer val){ 16 | auto session = val.get(); 17 | this->id(session->id()); 18 | this->content(session->content()); 19 | this->scene(session->scene()); 20 | this->type(session->type()); 21 | this->subType(session->subType()); 22 | this->extra(session->extra()); 23 | this->timestamp(session->timestamp()); 24 | this->unreadCount(session->unreadCount()); 25 | this->status(session->status()); 26 | this->stayTop(session->stayTop()); 27 | this->text(session->text()); 28 | this->time(session->time()); 29 | this->draft(session->draft()); 30 | } 31 | -------------------------------------------------------------------------------- /src/model/SessionModel.h: -------------------------------------------------------------------------------- 1 | #ifndef SESSIONMODEL_H 2 | #define SESSIONMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class SessionModel : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY_AUTO(QString,id) 12 | Q_PROPERTY_AUTO(QString,content) 13 | Q_PROPERTY_AUTO(int,scene) 14 | Q_PROPERTY_AUTO(int,type) 15 | Q_PROPERTY_AUTO(int,subType) 16 | Q_PROPERTY_AUTO(QString,extra) 17 | Q_PROPERTY_AUTO(qint64,timestamp) 18 | Q_PROPERTY_AUTO(int,unreadCount) 19 | Q_PROPERTY_AUTO(int,status) 20 | Q_PROPERTY_AUTO(bool,stayTop) 21 | 22 | Q_PROPERTY_AUTO(QString,text) 23 | Q_PROPERTY_AUTO(UserModel*,user) 24 | Q_PROPERTY_AUTO(QString,time) 25 | Q_PROPERTY_AUTO(QString,draft) 26 | 27 | void setModel(QSharedPointer val); 28 | 29 | public: 30 | explicit SessionModel(QObject *parent = nullptr); 31 | ~SessionModel(); 32 | 33 | }; 34 | 35 | #endif // SESSIONMODEL_H 36 | -------------------------------------------------------------------------------- /src/model/UserModel.cpp: -------------------------------------------------------------------------------- 1 | #include "UserModel.h" 2 | 3 | UserModel::UserModel(QObject *parent) 4 | : QObject{parent} 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/model/UserModel.h: -------------------------------------------------------------------------------- 1 | #ifndef USERMODEL_H 2 | #define USERMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class UserModel : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY_AUTO(QString,id) 12 | Q_PROPERTY_AUTO(QString,avatar) 13 | Q_PROPERTY_AUTO(qint64,birthday) 14 | Q_PROPERTY_AUTO(QString,extension) 15 | Q_PROPERTY_AUTO(int,gender) 16 | Q_PROPERTY_AUTO(QString,mobile) 17 | Q_PROPERTY_AUTO(QString,email) 18 | Q_PROPERTY_AUTO(QString,name) 19 | Q_PROPERTY_AUTO(QString,signature) 20 | Q_PROPERTY_AUTO(QString,uid) 21 | public: 22 | explicit UserModel(QObject *parent = nullptr); 23 | signals: 24 | 25 | }; 26 | 27 | #endif // USERMODEL_H 28 | -------------------------------------------------------------------------------- /src/proto/ReplyBody.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: ReplyBody.proto 3 | 4 | #ifndef GOOGLE_PROTOBUF_INCLUDED_ReplyBody_2eproto_2epb_2eh 5 | #define GOOGLE_PROTOBUF_INCLUDED_ReplyBody_2eproto_2epb_2eh 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "google/protobuf/port_def.inc" 12 | #if PROTOBUF_VERSION < 4024000 13 | #error "This file was generated by a newer version of protoc which is" 14 | #error "incompatible with your Protocol Buffer headers. Please update" 15 | #error "your headers." 16 | #endif // PROTOBUF_VERSION 17 | 18 | #if 4024004 < PROTOBUF_MIN_PROTOC_VERSION 19 | #error "This file was generated by an older version of protoc which is" 20 | #error "incompatible with your Protocol Buffer headers. Please" 21 | #error "regenerate this file with a newer version of protoc." 22 | #endif // PROTOBUF_MIN_PROTOC_VERSION 23 | #include "google/protobuf/port_undef.inc" 24 | #include "google/protobuf/io/coded_stream.h" 25 | #include "google/protobuf/arena.h" 26 | #include "google/protobuf/arenastring.h" 27 | #include "google/protobuf/generated_message_tctable_decl.h" 28 | #include "google/protobuf/generated_message_util.h" 29 | #include "google/protobuf/metadata_lite.h" 30 | #include "google/protobuf/generated_message_reflection.h" 31 | #include "google/protobuf/message.h" 32 | #include "google/protobuf/repeated_field.h" // IWYU pragma: export 33 | #include "google/protobuf/extension_set.h" // IWYU pragma: export 34 | #include "google/protobuf/map.h" // IWYU pragma: export 35 | #include "google/protobuf/map_entry.h" 36 | #include "google/protobuf/map_field_inl.h" 37 | #include "google/protobuf/unknown_field_set.h" 38 | // @@protoc_insertion_point(includes) 39 | 40 | // Must be included last. 41 | #include "google/protobuf/port_def.inc" 42 | 43 | #define PROTOBUF_INTERNAL_EXPORT_ReplyBody_2eproto 44 | 45 | namespace google { 46 | namespace protobuf { 47 | namespace internal { 48 | class AnyMetadata; 49 | } // namespace internal 50 | } // namespace protobuf 51 | } // namespace google 52 | 53 | // Internal implementation detail -- do not use these members. 54 | struct TableStruct_ReplyBody_2eproto { 55 | static const ::uint32_t offsets[]; 56 | }; 57 | extern const ::google::protobuf::internal::DescriptorTable 58 | descriptor_table_ReplyBody_2eproto; 59 | namespace com { 60 | namespace chuzi { 61 | namespace imsdk { 62 | namespace server { 63 | namespace model { 64 | namespace proto { 65 | class ReplyBody; 66 | struct ReplyBodyDefaultTypeInternal; 67 | extern ReplyBodyDefaultTypeInternal _ReplyBody_default_instance_; 68 | class ReplyBody_DataEntry_DoNotUse; 69 | struct ReplyBody_DataEntry_DoNotUseDefaultTypeInternal; 70 | extern ReplyBody_DataEntry_DoNotUseDefaultTypeInternal _ReplyBody_DataEntry_DoNotUse_default_instance_; 71 | } // namespace proto 72 | } // namespace model 73 | } // namespace server 74 | } // namespace imsdk 75 | } // namespace chuzi 76 | } // namespace com 77 | namespace google { 78 | namespace protobuf { 79 | } // namespace protobuf 80 | } // namespace google 81 | 82 | namespace com { 83 | namespace chuzi { 84 | namespace imsdk { 85 | namespace server { 86 | namespace model { 87 | namespace proto { 88 | 89 | // =================================================================== 90 | 91 | 92 | // ------------------------------------------------------------------- 93 | 94 | class ReplyBody_DataEntry_DoNotUse final : public ::google::protobuf::internal::MapEntry { 98 | public: 99 | typedef ::google::protobuf::internal::MapEntry SuperType; 103 | ReplyBody_DataEntry_DoNotUse(); 104 | template 105 | explicit PROTOBUF_CONSTEXPR ReplyBody_DataEntry_DoNotUse( 106 | ::google::protobuf::internal::ConstantInitialized); 107 | explicit ReplyBody_DataEntry_DoNotUse(::google::protobuf::Arena* arena); 108 | void MergeFrom(const ReplyBody_DataEntry_DoNotUse& other); 109 | static const ReplyBody_DataEntry_DoNotUse* internal_default_instance() { return reinterpret_cast(&_ReplyBody_DataEntry_DoNotUse_default_instance_); } 110 | static bool ValidateKey(std::string* s) { 111 | return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "com.chuzi.imsdk.server.model.proto.ReplyBody.DataEntry.key"); 112 | } 113 | static bool ValidateValue(std::string* s) { 114 | return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "com.chuzi.imsdk.server.model.proto.ReplyBody.DataEntry.value"); 115 | } 116 | using ::google::protobuf::Message::MergeFrom; 117 | ::google::protobuf::Metadata GetMetadata() const final; 118 | friend struct ::TableStruct_ReplyBody_2eproto; 119 | }; 120 | // ------------------------------------------------------------------- 121 | 122 | class ReplyBody final : 123 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:com.chuzi.imsdk.server.model.proto.ReplyBody) */ { 124 | public: 125 | inline ReplyBody() : ReplyBody(nullptr) {} 126 | ~ReplyBody() override; 127 | template 128 | explicit PROTOBUF_CONSTEXPR ReplyBody(::google::protobuf::internal::ConstantInitialized); 129 | 130 | ReplyBody(const ReplyBody& from); 131 | ReplyBody(ReplyBody&& from) noexcept 132 | : ReplyBody() { 133 | *this = ::std::move(from); 134 | } 135 | 136 | inline ReplyBody& operator=(const ReplyBody& from) { 137 | CopyFrom(from); 138 | return *this; 139 | } 140 | inline ReplyBody& operator=(ReplyBody&& from) noexcept { 141 | if (this == &from) return *this; 142 | if (GetOwningArena() == from.GetOwningArena() 143 | #ifdef PROTOBUF_FORCE_COPY_IN_MOVE 144 | && GetOwningArena() != nullptr 145 | #endif // !PROTOBUF_FORCE_COPY_IN_MOVE 146 | ) { 147 | InternalSwap(&from); 148 | } else { 149 | CopyFrom(from); 150 | } 151 | return *this; 152 | } 153 | 154 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 155 | return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); 156 | } 157 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 158 | return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); 159 | } 160 | 161 | static const ::google::protobuf::Descriptor* descriptor() { 162 | return GetDescriptor(); 163 | } 164 | static const ::google::protobuf::Descriptor* GetDescriptor() { 165 | return default_instance().GetMetadata().descriptor; 166 | } 167 | static const ::google::protobuf::Reflection* GetReflection() { 168 | return default_instance().GetMetadata().reflection; 169 | } 170 | static const ReplyBody& default_instance() { 171 | return *internal_default_instance(); 172 | } 173 | static inline const ReplyBody* internal_default_instance() { 174 | return reinterpret_cast( 175 | &_ReplyBody_default_instance_); 176 | } 177 | static constexpr int kIndexInFileMessages = 178 | 1; 179 | 180 | friend void swap(ReplyBody& a, ReplyBody& b) { 181 | a.Swap(&b); 182 | } 183 | inline void Swap(ReplyBody* other) { 184 | if (other == this) return; 185 | #ifdef PROTOBUF_FORCE_COPY_IN_SWAP 186 | if (GetOwningArena() != nullptr && 187 | GetOwningArena() == other->GetOwningArena()) { 188 | #else // PROTOBUF_FORCE_COPY_IN_SWAP 189 | if (GetOwningArena() == other->GetOwningArena()) { 190 | #endif // !PROTOBUF_FORCE_COPY_IN_SWAP 191 | InternalSwap(other); 192 | } else { 193 | ::google::protobuf::internal::GenericSwap(this, other); 194 | } 195 | } 196 | void UnsafeArenaSwap(ReplyBody* other) { 197 | if (other == this) return; 198 | ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); 199 | InternalSwap(other); 200 | } 201 | 202 | // implements Message ---------------------------------------------- 203 | 204 | ReplyBody* New(::google::protobuf::Arena* arena = nullptr) const final { 205 | return CreateMaybeMessage(arena); 206 | } 207 | using ::google::protobuf::Message::CopyFrom; 208 | void CopyFrom(const ReplyBody& from); 209 | using ::google::protobuf::Message::MergeFrom; 210 | void MergeFrom( const ReplyBody& from) { 211 | ReplyBody::MergeImpl(*this, from); 212 | } 213 | private: 214 | static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); 215 | public: 216 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 217 | bool IsInitialized() const final; 218 | 219 | ::size_t ByteSizeLong() const final; 220 | const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; 221 | ::uint8_t* _InternalSerialize( 222 | ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; 223 | int GetCachedSize() const final { return _impl_._cached_size_.Get(); } 224 | 225 | private: 226 | void SharedCtor(::google::protobuf::Arena* arena); 227 | void SharedDtor(); 228 | void SetCachedSize(int size) const final; 229 | void InternalSwap(ReplyBody* other); 230 | 231 | private: 232 | friend class ::google::protobuf::internal::AnyMetadata; 233 | static ::absl::string_view FullMessageName() { 234 | return "com.chuzi.imsdk.server.model.proto.ReplyBody"; 235 | } 236 | protected: 237 | explicit ReplyBody(::google::protobuf::Arena* arena); 238 | public: 239 | 240 | static const ClassData _class_data_; 241 | const ::google::protobuf::Message::ClassData*GetClassData() const final; 242 | 243 | ::google::protobuf::Metadata GetMetadata() const final; 244 | 245 | // nested types ---------------------------------------------------- 246 | 247 | 248 | // accessors ------------------------------------------------------- 249 | 250 | enum : int { 251 | kDataFieldNumber = 5, 252 | kKeyFieldNumber = 1, 253 | kCodeFieldNumber = 2, 254 | kMessageFieldNumber = 3, 255 | kTimestampFieldNumber = 4, 256 | }; 257 | // map data = 5; 258 | int data_size() const; 259 | private: 260 | int _internal_data_size() const; 261 | 262 | public: 263 | void clear_data() ; 264 | const ::google::protobuf::Map& data() const; 265 | ::google::protobuf::Map* mutable_data(); 266 | 267 | private: 268 | const ::google::protobuf::Map& _internal_data() const; 269 | ::google::protobuf::Map* _internal_mutable_data(); 270 | 271 | public: 272 | // string key = 1; 273 | void clear_key() ; 274 | const std::string& key() const; 275 | template 276 | void set_key(Arg_&& arg, Args_... args); 277 | std::string* mutable_key(); 278 | PROTOBUF_NODISCARD std::string* release_key(); 279 | void set_allocated_key(std::string* ptr); 280 | 281 | private: 282 | const std::string& _internal_key() const; 283 | inline PROTOBUF_ALWAYS_INLINE void _internal_set_key( 284 | const std::string& value); 285 | std::string* _internal_mutable_key(); 286 | 287 | public: 288 | // string code = 2; 289 | void clear_code() ; 290 | const std::string& code() const; 291 | template 292 | void set_code(Arg_&& arg, Args_... args); 293 | std::string* mutable_code(); 294 | PROTOBUF_NODISCARD std::string* release_code(); 295 | void set_allocated_code(std::string* ptr); 296 | 297 | private: 298 | const std::string& _internal_code() const; 299 | inline PROTOBUF_ALWAYS_INLINE void _internal_set_code( 300 | const std::string& value); 301 | std::string* _internal_mutable_code(); 302 | 303 | public: 304 | // string message = 3; 305 | void clear_message() ; 306 | const std::string& message() const; 307 | template 308 | void set_message(Arg_&& arg, Args_... args); 309 | std::string* mutable_message(); 310 | PROTOBUF_NODISCARD std::string* release_message(); 311 | void set_allocated_message(std::string* ptr); 312 | 313 | private: 314 | const std::string& _internal_message() const; 315 | inline PROTOBUF_ALWAYS_INLINE void _internal_set_message( 316 | const std::string& value); 317 | std::string* _internal_mutable_message(); 318 | 319 | public: 320 | // int64 timestamp = 4; 321 | void clear_timestamp() ; 322 | ::int64_t timestamp() const; 323 | void set_timestamp(::int64_t value); 324 | 325 | private: 326 | ::int64_t _internal_timestamp() const; 327 | void _internal_set_timestamp(::int64_t value); 328 | 329 | public: 330 | // @@protoc_insertion_point(class_scope:com.chuzi.imsdk.server.model.proto.ReplyBody) 331 | private: 332 | class _Internal; 333 | 334 | friend class ::google::protobuf::internal::TcParser; 335 | static const ::google::protobuf::internal::TcParseTable<2, 5, 1, 71, 2> _table_; 336 | template friend class ::google::protobuf::Arena::InternalHelper; 337 | typedef void InternalArenaConstructable_; 338 | typedef void DestructorSkippable_; 339 | struct Impl_ { 340 | ::google::protobuf::internal::MapField 343 | data_; 344 | ::google::protobuf::internal::ArenaStringPtr key_; 345 | ::google::protobuf::internal::ArenaStringPtr code_; 346 | ::google::protobuf::internal::ArenaStringPtr message_; 347 | ::int64_t timestamp_; 348 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 349 | PROTOBUF_TSAN_DECLARE_MEMBER 350 | }; 351 | union { Impl_ _impl_; }; 352 | friend struct ::TableStruct_ReplyBody_2eproto; 353 | }; 354 | 355 | // =================================================================== 356 | 357 | 358 | 359 | 360 | // =================================================================== 361 | 362 | 363 | #ifdef __GNUC__ 364 | #pragma GCC diagnostic push 365 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 366 | #endif // __GNUC__ 367 | // ------------------------------------------------------------------- 368 | 369 | // ------------------------------------------------------------------- 370 | 371 | // ReplyBody 372 | 373 | // string key = 1; 374 | inline void ReplyBody::clear_key() { 375 | _impl_.key_.ClearToEmpty(); 376 | } 377 | inline const std::string& ReplyBody::key() const { 378 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.ReplyBody.key) 379 | return _internal_key(); 380 | } 381 | template 382 | inline PROTOBUF_ALWAYS_INLINE void ReplyBody::set_key(Arg_&& arg, 383 | Args_... args) { 384 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 385 | ; 386 | _impl_.key_.Set(static_cast(arg), args..., GetArenaForAllocation()); 387 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.ReplyBody.key) 388 | } 389 | inline std::string* ReplyBody::mutable_key() { 390 | std::string* _s = _internal_mutable_key(); 391 | // @@protoc_insertion_point(field_mutable:com.chuzi.imsdk.server.model.proto.ReplyBody.key) 392 | return _s; 393 | } 394 | inline const std::string& ReplyBody::_internal_key() const { 395 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 396 | return _impl_.key_.Get(); 397 | } 398 | inline void ReplyBody::_internal_set_key(const std::string& value) { 399 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 400 | ; 401 | _impl_.key_.Set(value, GetArenaForAllocation()); 402 | } 403 | inline std::string* ReplyBody::_internal_mutable_key() { 404 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 405 | ; 406 | return _impl_.key_.Mutable( GetArenaForAllocation()); 407 | } 408 | inline std::string* ReplyBody::release_key() { 409 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 410 | // @@protoc_insertion_point(field_release:com.chuzi.imsdk.server.model.proto.ReplyBody.key) 411 | return _impl_.key_.Release(); 412 | } 413 | inline void ReplyBody::set_allocated_key(std::string* value) { 414 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 415 | _impl_.key_.SetAllocated(value, GetArenaForAllocation()); 416 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 417 | if (_impl_.key_.IsDefault()) { 418 | _impl_.key_.Set("", GetArenaForAllocation()); 419 | } 420 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 421 | // @@protoc_insertion_point(field_set_allocated:com.chuzi.imsdk.server.model.proto.ReplyBody.key) 422 | } 423 | 424 | // string code = 2; 425 | inline void ReplyBody::clear_code() { 426 | _impl_.code_.ClearToEmpty(); 427 | } 428 | inline const std::string& ReplyBody::code() const { 429 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.ReplyBody.code) 430 | return _internal_code(); 431 | } 432 | template 433 | inline PROTOBUF_ALWAYS_INLINE void ReplyBody::set_code(Arg_&& arg, 434 | Args_... args) { 435 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 436 | ; 437 | _impl_.code_.Set(static_cast(arg), args..., GetArenaForAllocation()); 438 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.ReplyBody.code) 439 | } 440 | inline std::string* ReplyBody::mutable_code() { 441 | std::string* _s = _internal_mutable_code(); 442 | // @@protoc_insertion_point(field_mutable:com.chuzi.imsdk.server.model.proto.ReplyBody.code) 443 | return _s; 444 | } 445 | inline const std::string& ReplyBody::_internal_code() const { 446 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 447 | return _impl_.code_.Get(); 448 | } 449 | inline void ReplyBody::_internal_set_code(const std::string& value) { 450 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 451 | ; 452 | _impl_.code_.Set(value, GetArenaForAllocation()); 453 | } 454 | inline std::string* ReplyBody::_internal_mutable_code() { 455 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 456 | ; 457 | return _impl_.code_.Mutable( GetArenaForAllocation()); 458 | } 459 | inline std::string* ReplyBody::release_code() { 460 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 461 | // @@protoc_insertion_point(field_release:com.chuzi.imsdk.server.model.proto.ReplyBody.code) 462 | return _impl_.code_.Release(); 463 | } 464 | inline void ReplyBody::set_allocated_code(std::string* value) { 465 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 466 | _impl_.code_.SetAllocated(value, GetArenaForAllocation()); 467 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 468 | if (_impl_.code_.IsDefault()) { 469 | _impl_.code_.Set("", GetArenaForAllocation()); 470 | } 471 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 472 | // @@protoc_insertion_point(field_set_allocated:com.chuzi.imsdk.server.model.proto.ReplyBody.code) 473 | } 474 | 475 | // string message = 3; 476 | inline void ReplyBody::clear_message() { 477 | _impl_.message_.ClearToEmpty(); 478 | } 479 | inline const std::string& ReplyBody::message() const { 480 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.ReplyBody.message) 481 | return _internal_message(); 482 | } 483 | template 484 | inline PROTOBUF_ALWAYS_INLINE void ReplyBody::set_message(Arg_&& arg, 485 | Args_... args) { 486 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 487 | ; 488 | _impl_.message_.Set(static_cast(arg), args..., GetArenaForAllocation()); 489 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.ReplyBody.message) 490 | } 491 | inline std::string* ReplyBody::mutable_message() { 492 | std::string* _s = _internal_mutable_message(); 493 | // @@protoc_insertion_point(field_mutable:com.chuzi.imsdk.server.model.proto.ReplyBody.message) 494 | return _s; 495 | } 496 | inline const std::string& ReplyBody::_internal_message() const { 497 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 498 | return _impl_.message_.Get(); 499 | } 500 | inline void ReplyBody::_internal_set_message(const std::string& value) { 501 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 502 | ; 503 | _impl_.message_.Set(value, GetArenaForAllocation()); 504 | } 505 | inline std::string* ReplyBody::_internal_mutable_message() { 506 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 507 | ; 508 | return _impl_.message_.Mutable( GetArenaForAllocation()); 509 | } 510 | inline std::string* ReplyBody::release_message() { 511 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 512 | // @@protoc_insertion_point(field_release:com.chuzi.imsdk.server.model.proto.ReplyBody.message) 513 | return _impl_.message_.Release(); 514 | } 515 | inline void ReplyBody::set_allocated_message(std::string* value) { 516 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 517 | _impl_.message_.SetAllocated(value, GetArenaForAllocation()); 518 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 519 | if (_impl_.message_.IsDefault()) { 520 | _impl_.message_.Set("", GetArenaForAllocation()); 521 | } 522 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 523 | // @@protoc_insertion_point(field_set_allocated:com.chuzi.imsdk.server.model.proto.ReplyBody.message) 524 | } 525 | 526 | // int64 timestamp = 4; 527 | inline void ReplyBody::clear_timestamp() { 528 | _impl_.timestamp_ = ::int64_t{0}; 529 | } 530 | inline ::int64_t ReplyBody::timestamp() const { 531 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.ReplyBody.timestamp) 532 | return _internal_timestamp(); 533 | } 534 | inline void ReplyBody::set_timestamp(::int64_t value) { 535 | _internal_set_timestamp(value); 536 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.ReplyBody.timestamp) 537 | } 538 | inline ::int64_t ReplyBody::_internal_timestamp() const { 539 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 540 | return _impl_.timestamp_; 541 | } 542 | inline void ReplyBody::_internal_set_timestamp(::int64_t value) { 543 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 544 | ; 545 | _impl_.timestamp_ = value; 546 | } 547 | 548 | // map data = 5; 549 | inline int ReplyBody::_internal_data_size() const { 550 | return _internal_data().size(); 551 | } 552 | inline int ReplyBody::data_size() const { 553 | return _internal_data_size(); 554 | } 555 | inline void ReplyBody::clear_data() { 556 | _impl_.data_.Clear(); 557 | } 558 | inline const ::google::protobuf::Map& ReplyBody::_internal_data() const { 559 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 560 | return _impl_.data_.GetMap(); 561 | } 562 | inline const ::google::protobuf::Map& ReplyBody::data() const { 563 | // @@protoc_insertion_point(field_map:com.chuzi.imsdk.server.model.proto.ReplyBody.data) 564 | return _internal_data(); 565 | } 566 | inline ::google::protobuf::Map* ReplyBody::_internal_mutable_data() { 567 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 568 | return _impl_.data_.MutableMap(); 569 | } 570 | inline ::google::protobuf::Map* ReplyBody::mutable_data() { 571 | // @@protoc_insertion_point(field_mutable_map:com.chuzi.imsdk.server.model.proto.ReplyBody.data) 572 | return _internal_mutable_data(); 573 | } 574 | 575 | #ifdef __GNUC__ 576 | #pragma GCC diagnostic pop 577 | #endif // __GNUC__ 578 | 579 | // @@protoc_insertion_point(namespace_scope) 580 | } // namespace proto 581 | } // namespace model 582 | } // namespace server 583 | } // namespace imsdk 584 | } // namespace chuzi 585 | } // namespace com 586 | 587 | 588 | // @@protoc_insertion_point(global_scope) 589 | 590 | #include "google/protobuf/port_undef.inc" 591 | 592 | #endif // GOOGLE_PROTOBUF_INCLUDED_ReplyBody_2eproto_2epb_2eh 593 | -------------------------------------------------------------------------------- /src/proto/SentBody.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: SentBody.proto 3 | 4 | #include "SentBody.pb.h" 5 | 6 | #include 7 | #include "google/protobuf/io/coded_stream.h" 8 | #include "google/protobuf/extension_set.h" 9 | #include "google/protobuf/wire_format_lite.h" 10 | #include "google/protobuf/descriptor.h" 11 | #include "google/protobuf/generated_message_reflection.h" 12 | #include "google/protobuf/reflection_ops.h" 13 | #include "google/protobuf/wire_format.h" 14 | #include "google/protobuf/generated_message_tctable_impl.h" 15 | // @@protoc_insertion_point(includes) 16 | 17 | // Must be included last. 18 | #include "google/protobuf/port_def.inc" 19 | PROTOBUF_PRAGMA_INIT_SEG 20 | namespace _pb = ::google::protobuf; 21 | namespace _pbi = ::google::protobuf::internal; 22 | namespace _fl = ::google::protobuf::internal::field_layout; 23 | namespace com { 24 | namespace chuzi { 25 | namespace imsdk { 26 | namespace server { 27 | namespace model { 28 | namespace proto { 29 | template 30 | PROTOBUF_CONSTEXPR SentBody_DataEntry_DoNotUse::SentBody_DataEntry_DoNotUse(::_pbi::ConstantInitialized) {} 31 | struct SentBody_DataEntry_DoNotUseDefaultTypeInternal { 32 | PROTOBUF_CONSTEXPR SentBody_DataEntry_DoNotUseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} 33 | ~SentBody_DataEntry_DoNotUseDefaultTypeInternal() {} 34 | union { 35 | SentBody_DataEntry_DoNotUse _instance; 36 | }; 37 | }; 38 | 39 | PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT 40 | PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SentBody_DataEntry_DoNotUseDefaultTypeInternal _SentBody_DataEntry_DoNotUse_default_instance_; 41 | template 42 | PROTOBUF_CONSTEXPR SentBody::SentBody(::_pbi::ConstantInitialized) 43 | : _impl_{ 44 | /* decltype(_impl_.data_) */ {}, 45 | /*decltype(_impl_.key_)*/ { 46 | &::_pbi::fixed_address_empty_string, 47 | ::_pbi::ConstantInitialized{}, 48 | }, 49 | /*decltype(_impl_.timestamp_)*/ ::int64_t{0}, 50 | /*decltype(_impl_._cached_size_)*/ {}, 51 | } {} 52 | struct SentBodyDefaultTypeInternal { 53 | PROTOBUF_CONSTEXPR SentBodyDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} 54 | ~SentBodyDefaultTypeInternal() {} 55 | union { 56 | SentBody _instance; 57 | }; 58 | }; 59 | 60 | PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT 61 | PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SentBodyDefaultTypeInternal _SentBody_default_instance_; 62 | } // namespace proto 63 | } // namespace model 64 | } // namespace server 65 | } // namespace imsdk 66 | } // namespace chuzi 67 | } // namespace com 68 | static ::_pb::Metadata file_level_metadata_SentBody_2eproto[2]; 69 | static constexpr const ::_pb::EnumDescriptor** 70 | file_level_enum_descriptors_SentBody_2eproto = nullptr; 71 | static constexpr const ::_pb::ServiceDescriptor** 72 | file_level_service_descriptors_SentBody_2eproto = nullptr; 73 | const ::uint32_t TableStruct_SentBody_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( 74 | protodesc_cold) = { 75 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody_DataEntry_DoNotUse, _has_bits_), 76 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody_DataEntry_DoNotUse, _internal_metadata_), 77 | ~0u, // no _extensions_ 78 | ~0u, // no _oneof_case_ 79 | ~0u, // no _weak_field_map_ 80 | ~0u, // no _inlined_string_donated_ 81 | ~0u, // no _split_ 82 | ~0u, // no sizeof(Split) 83 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody_DataEntry_DoNotUse, key_), 84 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody_DataEntry_DoNotUse, value_), 85 | 0, 86 | 1, 87 | ~0u, // no _has_bits_ 88 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody, _internal_metadata_), 89 | ~0u, // no _extensions_ 90 | ~0u, // no _oneof_case_ 91 | ~0u, // no _weak_field_map_ 92 | ~0u, // no _inlined_string_donated_ 93 | ~0u, // no _split_ 94 | ~0u, // no sizeof(Split) 95 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody, _impl_.key_), 96 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody, _impl_.timestamp_), 97 | PROTOBUF_FIELD_OFFSET(::com::chuzi::imsdk::server::model::proto::SentBody, _impl_.data_), 98 | }; 99 | 100 | static const ::_pbi::MigrationSchema 101 | schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 102 | {0, 10, -1, sizeof(::com::chuzi::imsdk::server::model::proto::SentBody_DataEntry_DoNotUse)}, 103 | {12, -1, -1, sizeof(::com::chuzi::imsdk::server::model::proto::SentBody)}, 104 | }; 105 | 106 | static const ::_pb::Message* const file_default_instances[] = { 107 | &::com::chuzi::imsdk::server::model::proto::_SentBody_DataEntry_DoNotUse_default_instance_._instance, 108 | &::com::chuzi::imsdk::server::model::proto::_SentBody_default_instance_._instance, 109 | }; 110 | const char descriptor_table_protodef_SentBody_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 111 | "\n\016SentBody.proto\022\"com.chuzi.imsdk.server" 112 | ".model.proto\"\235\001\n\010SentBody\022\013\n\003key\030\001 \001(\t\022\021" 113 | "\n\ttimestamp\030\002 \001(\003\022D\n\004data\030\003 \003(\01326.com.ch" 114 | "uzi.imsdk.server.model.proto.SentBody.Da" 115 | "taEntry\032+\n\tDataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005val" 116 | "ue\030\002 \001(\t:\0028\001B\017B\rSentBodyProtob\006proto3" 117 | }; 118 | static ::absl::once_flag descriptor_table_SentBody_2eproto_once; 119 | const ::_pbi::DescriptorTable descriptor_table_SentBody_2eproto = { 120 | false, 121 | false, 122 | 237, 123 | descriptor_table_protodef_SentBody_2eproto, 124 | "SentBody.proto", 125 | &descriptor_table_SentBody_2eproto_once, 126 | nullptr, 127 | 0, 128 | 2, 129 | schemas, 130 | file_default_instances, 131 | TableStruct_SentBody_2eproto::offsets, 132 | file_level_metadata_SentBody_2eproto, 133 | file_level_enum_descriptors_SentBody_2eproto, 134 | file_level_service_descriptors_SentBody_2eproto, 135 | }; 136 | 137 | // This function exists to be marked as weak. 138 | // It can significantly speed up compilation by breaking up LLVM's SCC 139 | // in the .pb.cc translation units. Large translation units see a 140 | // reduction of more than 35% of walltime for optimized builds. Without 141 | // the weak attribute all the messages in the file, including all the 142 | // vtables and everything they use become part of the same SCC through 143 | // a cycle like: 144 | // GetMetadata -> descriptor table -> default instances -> 145 | // vtables -> GetMetadata 146 | // By adding a weak function here we break the connection from the 147 | // individual vtables back into the descriptor table. 148 | PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_SentBody_2eproto_getter() { 149 | return &descriptor_table_SentBody_2eproto; 150 | } 151 | // Force running AddDescriptors() at dynamic initialization time. 152 | PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 153 | static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_SentBody_2eproto(&descriptor_table_SentBody_2eproto); 154 | namespace com { 155 | namespace chuzi { 156 | namespace imsdk { 157 | namespace server { 158 | namespace model { 159 | namespace proto { 160 | // =================================================================== 161 | 162 | SentBody_DataEntry_DoNotUse::SentBody_DataEntry_DoNotUse() {} 163 | SentBody_DataEntry_DoNotUse::SentBody_DataEntry_DoNotUse(::google::protobuf::Arena* arena) 164 | : SuperType(arena) {} 165 | void SentBody_DataEntry_DoNotUse::MergeFrom(const SentBody_DataEntry_DoNotUse& other) { 166 | MergeFromInternal(other); 167 | } 168 | ::google::protobuf::Metadata SentBody_DataEntry_DoNotUse::GetMetadata() const { 169 | return ::_pbi::AssignDescriptors( 170 | &descriptor_table_SentBody_2eproto_getter, &descriptor_table_SentBody_2eproto_once, 171 | file_level_metadata_SentBody_2eproto[0]); 172 | } 173 | // =================================================================== 174 | 175 | class SentBody::_Internal { 176 | public: 177 | }; 178 | 179 | SentBody::SentBody(::google::protobuf::Arena* arena) 180 | : ::google::protobuf::Message(arena) { 181 | SharedCtor(arena); 182 | // @@protoc_insertion_point(arena_constructor:com.chuzi.imsdk.server.model.proto.SentBody) 183 | } 184 | SentBody::SentBody(const SentBody& from) : ::google::protobuf::Message() { 185 | SentBody* const _this = this; 186 | (void)_this; 187 | new (&_impl_) Impl_{ 188 | /* decltype(_impl_.data_) */ {}, 189 | decltype(_impl_.key_){}, 190 | decltype(_impl_.timestamp_){}, 191 | /*decltype(_impl_._cached_size_)*/ {}, 192 | }; 193 | _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( 194 | from._internal_metadata_); 195 | _this->_impl_.data_.MergeFrom(from._impl_.data_); 196 | _impl_.key_.InitDefault(); 197 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 198 | _impl_.key_.Set("", GetArenaForAllocation()); 199 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 200 | if (!from._internal_key().empty()) { 201 | _this->_impl_.key_.Set(from._internal_key(), _this->GetArenaForAllocation()); 202 | } 203 | _this->_impl_.timestamp_ = from._impl_.timestamp_; 204 | 205 | // @@protoc_insertion_point(copy_constructor:com.chuzi.imsdk.server.model.proto.SentBody) 206 | } 207 | inline void SentBody::SharedCtor(::_pb::Arena* arena) { 208 | (void)arena; 209 | new (&_impl_) Impl_{ 210 | /* decltype(_impl_.data_) */ {::google::protobuf::internal::ArenaInitialized(), arena}, 211 | decltype(_impl_.key_){}, 212 | decltype(_impl_.timestamp_){::int64_t{0}}, 213 | /*decltype(_impl_._cached_size_)*/ {}, 214 | }; 215 | _impl_.key_.InitDefault(); 216 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 217 | _impl_.key_.Set("", GetArenaForAllocation()); 218 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 219 | } 220 | SentBody::~SentBody() { 221 | // @@protoc_insertion_point(destructor:com.chuzi.imsdk.server.model.proto.SentBody) 222 | _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); 223 | SharedDtor(); 224 | } 225 | inline void SentBody::SharedDtor() { 226 | ABSL_DCHECK(GetArenaForAllocation() == nullptr); 227 | _impl_.data_.~MapField(); 228 | _impl_.key_.Destroy(); 229 | } 230 | void SentBody::SetCachedSize(int size) const { 231 | _impl_._cached_size_.Set(size); 232 | } 233 | 234 | PROTOBUF_NOINLINE void SentBody::Clear() { 235 | // @@protoc_insertion_point(message_clear_start:com.chuzi.imsdk.server.model.proto.SentBody) 236 | ::uint32_t cached_has_bits = 0; 237 | // Prevent compiler warnings about cached_has_bits being unused 238 | (void) cached_has_bits; 239 | 240 | _impl_.data_.Clear(); 241 | _impl_.key_.ClearToEmpty(); 242 | _impl_.timestamp_ = ::int64_t{0}; 243 | _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); 244 | } 245 | 246 | const char* SentBody::_InternalParse( 247 | const char* ptr, ::_pbi::ParseContext* ctx) { 248 | ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); 249 | return ptr; 250 | } 251 | 252 | 253 | PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 254 | const ::_pbi::TcParseTable<1, 3, 1, 59, 2> SentBody::_table_ = { 255 | { 256 | 0, // no _has_bits_ 257 | 0, // no _extensions_ 258 | 3, 8, // max_field_number, fast_idx_mask 259 | offsetof(decltype(_table_), field_lookup_table), 260 | 4294967288, // skipmap 261 | offsetof(decltype(_table_), field_entries), 262 | 3, // num_field_entries 263 | 1, // num_aux_entries 264 | offsetof(decltype(_table_), aux_entries), 265 | &_SentBody_default_instance_._instance, 266 | ::_pbi::TcParser::GenericFallback, // fallback 267 | }, {{ 268 | // int64 timestamp = 2; 269 | {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SentBody, _impl_.timestamp_), 63>(), 270 | {16, 63, 0, PROTOBUF_FIELD_OFFSET(SentBody, _impl_.timestamp_)}}, 271 | // string key = 1; 272 | {::_pbi::TcParser::FastUS1, 273 | {10, 63, 0, PROTOBUF_FIELD_OFFSET(SentBody, _impl_.key_)}}, 274 | }}, {{ 275 | 65535, 65535 276 | }}, {{ 277 | // string key = 1; 278 | {PROTOBUF_FIELD_OFFSET(SentBody, _impl_.key_), 0, 0, 279 | (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, 280 | // int64 timestamp = 2; 281 | {PROTOBUF_FIELD_OFFSET(SentBody, _impl_.timestamp_), 0, 0, 282 | (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, 283 | // map data = 3; 284 | {PROTOBUF_FIELD_OFFSET(SentBody, _impl_.data_), 0, 0, 285 | (0 | ::_fl::kFcRepeated | ::_fl::kMap)}, 286 | }}, {{ 287 | {::_pbi::TcParser::GetMapAuxInfo(1, 0, 0)}, 288 | }}, {{ 289 | "\53\3\0\4\0\0\0\0" 290 | "com.chuzi.imsdk.server.model.proto.SentBody" 291 | "key" 292 | "data" 293 | }}, 294 | }; 295 | 296 | ::uint8_t* SentBody::_InternalSerialize( 297 | ::uint8_t* target, 298 | ::google::protobuf::io::EpsCopyOutputStream* stream) const { 299 | // @@protoc_insertion_point(serialize_to_array_start:com.chuzi.imsdk.server.model.proto.SentBody) 300 | ::uint32_t cached_has_bits = 0; 301 | (void)cached_has_bits; 302 | 303 | // string key = 1; 304 | if (!this->_internal_key().empty()) { 305 | const std::string& _s = this->_internal_key(); 306 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 307 | _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "com.chuzi.imsdk.server.model.proto.SentBody.key"); 308 | target = stream->WriteStringMaybeAliased(1, _s, target); 309 | } 310 | 311 | // int64 timestamp = 2; 312 | if (this->_internal_timestamp() != 0) { 313 | target = ::google::protobuf::internal::WireFormatLite:: 314 | WriteInt64ToArrayWithField<2>( 315 | stream, this->_internal_timestamp(), target); 316 | } 317 | 318 | // map data = 3; 319 | if (!_internal_data().empty()) { 320 | using MapType = ::google::protobuf::Map; 321 | using WireHelper = SentBody_DataEntry_DoNotUse::Funcs; 322 | const auto& field = _internal_data(); 323 | 324 | if (stream->IsSerializationDeterministic() && field.size() > 1) { 325 | for (const auto& entry : ::google::protobuf::internal::MapSorterPtr(field)) { 326 | target = WireHelper::InternalSerialize( 327 | 3, entry.first, entry.second, target, stream); 328 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 329 | entry.first.data(), static_cast(entry.first.length()), 330 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, "com.chuzi.imsdk.server.model.proto.SentBody.data"); 331 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 332 | entry.second.data(), static_cast(entry.second.length()), 333 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, "com.chuzi.imsdk.server.model.proto.SentBody.data"); 334 | } 335 | } else { 336 | for (const auto& entry : field) { 337 | target = WireHelper::InternalSerialize( 338 | 3, entry.first, entry.second, target, stream); 339 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 340 | entry.first.data(), static_cast(entry.first.length()), 341 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, "com.chuzi.imsdk.server.model.proto.SentBody.data"); 342 | ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( 343 | entry.second.data(), static_cast(entry.second.length()), 344 | ::google::protobuf::internal::WireFormatLite::SERIALIZE, "com.chuzi.imsdk.server.model.proto.SentBody.data"); 345 | } 346 | } 347 | } 348 | 349 | if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { 350 | target = 351 | ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( 352 | _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); 353 | } 354 | // @@protoc_insertion_point(serialize_to_array_end:com.chuzi.imsdk.server.model.proto.SentBody) 355 | return target; 356 | } 357 | 358 | ::size_t SentBody::ByteSizeLong() const { 359 | // @@protoc_insertion_point(message_byte_size_start:com.chuzi.imsdk.server.model.proto.SentBody) 360 | ::size_t total_size = 0; 361 | 362 | ::uint32_t cached_has_bits = 0; 363 | // Prevent compiler warnings about cached_has_bits being unused 364 | (void) cached_has_bits; 365 | 366 | // map data = 3; 367 | total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_data_size()); 368 | for (const auto& entry : _internal_data()) { 369 | total_size += SentBody_DataEntry_DoNotUse::Funcs::ByteSizeLong(entry.first, entry.second); 370 | } 371 | // string key = 1; 372 | if (!this->_internal_key().empty()) { 373 | total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( 374 | this->_internal_key()); 375 | } 376 | 377 | // int64 timestamp = 2; 378 | if (this->_internal_timestamp() != 0) { 379 | total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( 380 | this->_internal_timestamp()); 381 | } 382 | 383 | return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); 384 | } 385 | 386 | const ::google::protobuf::Message::ClassData SentBody::_class_data_ = { 387 | ::google::protobuf::Message::CopyWithSourceCheck, 388 | SentBody::MergeImpl 389 | }; 390 | const ::google::protobuf::Message::ClassData*SentBody::GetClassData() const { return &_class_data_; } 391 | 392 | 393 | void SentBody::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { 394 | auto* const _this = static_cast(&to_msg); 395 | auto& from = static_cast(from_msg); 396 | // @@protoc_insertion_point(class_specific_merge_from_start:com.chuzi.imsdk.server.model.proto.SentBody) 397 | ABSL_DCHECK_NE(&from, _this); 398 | ::uint32_t cached_has_bits = 0; 399 | (void) cached_has_bits; 400 | 401 | _this->_impl_.data_.MergeFrom(from._impl_.data_); 402 | if (!from._internal_key().empty()) { 403 | _this->_internal_set_key(from._internal_key()); 404 | } 405 | if (from._internal_timestamp() != 0) { 406 | _this->_internal_set_timestamp(from._internal_timestamp()); 407 | } 408 | _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); 409 | } 410 | 411 | void SentBody::CopyFrom(const SentBody& from) { 412 | // @@protoc_insertion_point(class_specific_copy_from_start:com.chuzi.imsdk.server.model.proto.SentBody) 413 | if (&from == this) return; 414 | Clear(); 415 | MergeFrom(from); 416 | } 417 | 418 | PROTOBUF_NOINLINE bool SentBody::IsInitialized() const { 419 | return true; 420 | } 421 | 422 | void SentBody::InternalSwap(SentBody* other) { 423 | using std::swap; 424 | auto* lhs_arena = GetArenaForAllocation(); 425 | auto* rhs_arena = other->GetArenaForAllocation(); 426 | _internal_metadata_.InternalSwap(&other->_internal_metadata_); 427 | _impl_.data_.InternalSwap(&other->_impl_.data_); 428 | ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.key_, lhs_arena, 429 | &other->_impl_.key_, rhs_arena); 430 | swap(_impl_.timestamp_, other->_impl_.timestamp_); 431 | } 432 | 433 | ::google::protobuf::Metadata SentBody::GetMetadata() const { 434 | return ::_pbi::AssignDescriptors( 435 | &descriptor_table_SentBody_2eproto_getter, &descriptor_table_SentBody_2eproto_once, 436 | file_level_metadata_SentBody_2eproto[1]); 437 | } 438 | // @@protoc_insertion_point(namespace_scope) 439 | } // namespace proto 440 | } // namespace model 441 | } // namespace server 442 | } // namespace imsdk 443 | } // namespace chuzi 444 | } // namespace com 445 | namespace google { 446 | namespace protobuf { 447 | } // namespace protobuf 448 | } // namespace google 449 | // @@protoc_insertion_point(global_scope) 450 | #include "google/protobuf/port_undef.inc" 451 | -------------------------------------------------------------------------------- /src/proto/SentBody.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: SentBody.proto 3 | 4 | #ifndef GOOGLE_PROTOBUF_INCLUDED_SentBody_2eproto_2epb_2eh 5 | #define GOOGLE_PROTOBUF_INCLUDED_SentBody_2eproto_2epb_2eh 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "google/protobuf/port_def.inc" 12 | #if PROTOBUF_VERSION < 4024000 13 | #error "This file was generated by a newer version of protoc which is" 14 | #error "incompatible with your Protocol Buffer headers. Please update" 15 | #error "your headers." 16 | #endif // PROTOBUF_VERSION 17 | 18 | #if 4024004 < PROTOBUF_MIN_PROTOC_VERSION 19 | #error "This file was generated by an older version of protoc which is" 20 | #error "incompatible with your Protocol Buffer headers. Please" 21 | #error "regenerate this file with a newer version of protoc." 22 | #endif // PROTOBUF_MIN_PROTOC_VERSION 23 | #include "google/protobuf/port_undef.inc" 24 | #include "google/protobuf/io/coded_stream.h" 25 | #include "google/protobuf/arena.h" 26 | #include "google/protobuf/arenastring.h" 27 | #include "google/protobuf/generated_message_tctable_decl.h" 28 | #include "google/protobuf/generated_message_util.h" 29 | #include "google/protobuf/metadata_lite.h" 30 | #include "google/protobuf/generated_message_reflection.h" 31 | #include "google/protobuf/message.h" 32 | #include "google/protobuf/repeated_field.h" // IWYU pragma: export 33 | #include "google/protobuf/extension_set.h" // IWYU pragma: export 34 | #include "google/protobuf/map.h" // IWYU pragma: export 35 | #include "google/protobuf/map_entry.h" 36 | #include "google/protobuf/map_field_inl.h" 37 | #include "google/protobuf/unknown_field_set.h" 38 | // @@protoc_insertion_point(includes) 39 | 40 | // Must be included last. 41 | #include "google/protobuf/port_def.inc" 42 | 43 | #define PROTOBUF_INTERNAL_EXPORT_SentBody_2eproto 44 | 45 | namespace google { 46 | namespace protobuf { 47 | namespace internal { 48 | class AnyMetadata; 49 | } // namespace internal 50 | } // namespace protobuf 51 | } // namespace google 52 | 53 | // Internal implementation detail -- do not use these members. 54 | struct TableStruct_SentBody_2eproto { 55 | static const ::uint32_t offsets[]; 56 | }; 57 | extern const ::google::protobuf::internal::DescriptorTable 58 | descriptor_table_SentBody_2eproto; 59 | namespace com { 60 | namespace chuzi { 61 | namespace imsdk { 62 | namespace server { 63 | namespace model { 64 | namespace proto { 65 | class SentBody; 66 | struct SentBodyDefaultTypeInternal; 67 | extern SentBodyDefaultTypeInternal _SentBody_default_instance_; 68 | class SentBody_DataEntry_DoNotUse; 69 | struct SentBody_DataEntry_DoNotUseDefaultTypeInternal; 70 | extern SentBody_DataEntry_DoNotUseDefaultTypeInternal _SentBody_DataEntry_DoNotUse_default_instance_; 71 | } // namespace proto 72 | } // namespace model 73 | } // namespace server 74 | } // namespace imsdk 75 | } // namespace chuzi 76 | } // namespace com 77 | namespace google { 78 | namespace protobuf { 79 | } // namespace protobuf 80 | } // namespace google 81 | 82 | namespace com { 83 | namespace chuzi { 84 | namespace imsdk { 85 | namespace server { 86 | namespace model { 87 | namespace proto { 88 | 89 | // =================================================================== 90 | 91 | 92 | // ------------------------------------------------------------------- 93 | 94 | class SentBody_DataEntry_DoNotUse final : public ::google::protobuf::internal::MapEntry { 98 | public: 99 | typedef ::google::protobuf::internal::MapEntry SuperType; 103 | SentBody_DataEntry_DoNotUse(); 104 | template 105 | explicit PROTOBUF_CONSTEXPR SentBody_DataEntry_DoNotUse( 106 | ::google::protobuf::internal::ConstantInitialized); 107 | explicit SentBody_DataEntry_DoNotUse(::google::protobuf::Arena* arena); 108 | void MergeFrom(const SentBody_DataEntry_DoNotUse& other); 109 | static const SentBody_DataEntry_DoNotUse* internal_default_instance() { return reinterpret_cast(&_SentBody_DataEntry_DoNotUse_default_instance_); } 110 | static bool ValidateKey(std::string* s) { 111 | return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "com.chuzi.imsdk.server.model.proto.SentBody.DataEntry.key"); 112 | } 113 | static bool ValidateValue(std::string* s) { 114 | return ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast(s->size()), ::google::protobuf::internal::WireFormatLite::PARSE, "com.chuzi.imsdk.server.model.proto.SentBody.DataEntry.value"); 115 | } 116 | using ::google::protobuf::Message::MergeFrom; 117 | ::google::protobuf::Metadata GetMetadata() const final; 118 | friend struct ::TableStruct_SentBody_2eproto; 119 | }; 120 | // ------------------------------------------------------------------- 121 | 122 | class SentBody final : 123 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:com.chuzi.imsdk.server.model.proto.SentBody) */ { 124 | public: 125 | inline SentBody() : SentBody(nullptr) {} 126 | ~SentBody() override; 127 | template 128 | explicit PROTOBUF_CONSTEXPR SentBody(::google::protobuf::internal::ConstantInitialized); 129 | 130 | SentBody(const SentBody& from); 131 | SentBody(SentBody&& from) noexcept 132 | : SentBody() { 133 | *this = ::std::move(from); 134 | } 135 | 136 | inline SentBody& operator=(const SentBody& from) { 137 | CopyFrom(from); 138 | return *this; 139 | } 140 | inline SentBody& operator=(SentBody&& from) noexcept { 141 | if (this == &from) return *this; 142 | if (GetOwningArena() == from.GetOwningArena() 143 | #ifdef PROTOBUF_FORCE_COPY_IN_MOVE 144 | && GetOwningArena() != nullptr 145 | #endif // !PROTOBUF_FORCE_COPY_IN_MOVE 146 | ) { 147 | InternalSwap(&from); 148 | } else { 149 | CopyFrom(from); 150 | } 151 | return *this; 152 | } 153 | 154 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 155 | return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); 156 | } 157 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 158 | return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); 159 | } 160 | 161 | static const ::google::protobuf::Descriptor* descriptor() { 162 | return GetDescriptor(); 163 | } 164 | static const ::google::protobuf::Descriptor* GetDescriptor() { 165 | return default_instance().GetMetadata().descriptor; 166 | } 167 | static const ::google::protobuf::Reflection* GetReflection() { 168 | return default_instance().GetMetadata().reflection; 169 | } 170 | static const SentBody& default_instance() { 171 | return *internal_default_instance(); 172 | } 173 | static inline const SentBody* internal_default_instance() { 174 | return reinterpret_cast( 175 | &_SentBody_default_instance_); 176 | } 177 | static constexpr int kIndexInFileMessages = 178 | 1; 179 | 180 | friend void swap(SentBody& a, SentBody& b) { 181 | a.Swap(&b); 182 | } 183 | inline void Swap(SentBody* other) { 184 | if (other == this) return; 185 | #ifdef PROTOBUF_FORCE_COPY_IN_SWAP 186 | if (GetOwningArena() != nullptr && 187 | GetOwningArena() == other->GetOwningArena()) { 188 | #else // PROTOBUF_FORCE_COPY_IN_SWAP 189 | if (GetOwningArena() == other->GetOwningArena()) { 190 | #endif // !PROTOBUF_FORCE_COPY_IN_SWAP 191 | InternalSwap(other); 192 | } else { 193 | ::google::protobuf::internal::GenericSwap(this, other); 194 | } 195 | } 196 | void UnsafeArenaSwap(SentBody* other) { 197 | if (other == this) return; 198 | ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); 199 | InternalSwap(other); 200 | } 201 | 202 | // implements Message ---------------------------------------------- 203 | 204 | SentBody* New(::google::protobuf::Arena* arena = nullptr) const final { 205 | return CreateMaybeMessage(arena); 206 | } 207 | using ::google::protobuf::Message::CopyFrom; 208 | void CopyFrom(const SentBody& from); 209 | using ::google::protobuf::Message::MergeFrom; 210 | void MergeFrom( const SentBody& from) { 211 | SentBody::MergeImpl(*this, from); 212 | } 213 | private: 214 | static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); 215 | public: 216 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 217 | bool IsInitialized() const final; 218 | 219 | ::size_t ByteSizeLong() const final; 220 | const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; 221 | ::uint8_t* _InternalSerialize( 222 | ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; 223 | int GetCachedSize() const final { return _impl_._cached_size_.Get(); } 224 | 225 | private: 226 | void SharedCtor(::google::protobuf::Arena* arena); 227 | void SharedDtor(); 228 | void SetCachedSize(int size) const final; 229 | void InternalSwap(SentBody* other); 230 | 231 | private: 232 | friend class ::google::protobuf::internal::AnyMetadata; 233 | static ::absl::string_view FullMessageName() { 234 | return "com.chuzi.imsdk.server.model.proto.SentBody"; 235 | } 236 | protected: 237 | explicit SentBody(::google::protobuf::Arena* arena); 238 | public: 239 | 240 | static const ClassData _class_data_; 241 | const ::google::protobuf::Message::ClassData*GetClassData() const final; 242 | 243 | ::google::protobuf::Metadata GetMetadata() const final; 244 | 245 | // nested types ---------------------------------------------------- 246 | 247 | 248 | // accessors ------------------------------------------------------- 249 | 250 | enum : int { 251 | kDataFieldNumber = 3, 252 | kKeyFieldNumber = 1, 253 | kTimestampFieldNumber = 2, 254 | }; 255 | // map data = 3; 256 | int data_size() const; 257 | private: 258 | int _internal_data_size() const; 259 | 260 | public: 261 | void clear_data() ; 262 | const ::google::protobuf::Map& data() const; 263 | ::google::protobuf::Map* mutable_data(); 264 | 265 | private: 266 | const ::google::protobuf::Map& _internal_data() const; 267 | ::google::protobuf::Map* _internal_mutable_data(); 268 | 269 | public: 270 | // string key = 1; 271 | void clear_key() ; 272 | const std::string& key() const; 273 | template 274 | void set_key(Arg_&& arg, Args_... args); 275 | std::string* mutable_key(); 276 | PROTOBUF_NODISCARD std::string* release_key(); 277 | void set_allocated_key(std::string* ptr); 278 | 279 | private: 280 | const std::string& _internal_key() const; 281 | inline PROTOBUF_ALWAYS_INLINE void _internal_set_key( 282 | const std::string& value); 283 | std::string* _internal_mutable_key(); 284 | 285 | public: 286 | // int64 timestamp = 2; 287 | void clear_timestamp() ; 288 | ::int64_t timestamp() const; 289 | void set_timestamp(::int64_t value); 290 | 291 | private: 292 | ::int64_t _internal_timestamp() const; 293 | void _internal_set_timestamp(::int64_t value); 294 | 295 | public: 296 | // @@protoc_insertion_point(class_scope:com.chuzi.imsdk.server.model.proto.SentBody) 297 | private: 298 | class _Internal; 299 | 300 | friend class ::google::protobuf::internal::TcParser; 301 | static const ::google::protobuf::internal::TcParseTable<1, 3, 1, 59, 2> _table_; 302 | template friend class ::google::protobuf::Arena::InternalHelper; 303 | typedef void InternalArenaConstructable_; 304 | typedef void DestructorSkippable_; 305 | struct Impl_ { 306 | ::google::protobuf::internal::MapField 309 | data_; 310 | ::google::protobuf::internal::ArenaStringPtr key_; 311 | ::int64_t timestamp_; 312 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 313 | PROTOBUF_TSAN_DECLARE_MEMBER 314 | }; 315 | union { Impl_ _impl_; }; 316 | friend struct ::TableStruct_SentBody_2eproto; 317 | }; 318 | 319 | // =================================================================== 320 | 321 | 322 | 323 | 324 | // =================================================================== 325 | 326 | 327 | #ifdef __GNUC__ 328 | #pragma GCC diagnostic push 329 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 330 | #endif // __GNUC__ 331 | // ------------------------------------------------------------------- 332 | 333 | // ------------------------------------------------------------------- 334 | 335 | // SentBody 336 | 337 | // string key = 1; 338 | inline void SentBody::clear_key() { 339 | _impl_.key_.ClearToEmpty(); 340 | } 341 | inline const std::string& SentBody::key() const { 342 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.SentBody.key) 343 | return _internal_key(); 344 | } 345 | template 346 | inline PROTOBUF_ALWAYS_INLINE void SentBody::set_key(Arg_&& arg, 347 | Args_... args) { 348 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 349 | ; 350 | _impl_.key_.Set(static_cast(arg), args..., GetArenaForAllocation()); 351 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.SentBody.key) 352 | } 353 | inline std::string* SentBody::mutable_key() { 354 | std::string* _s = _internal_mutable_key(); 355 | // @@protoc_insertion_point(field_mutable:com.chuzi.imsdk.server.model.proto.SentBody.key) 356 | return _s; 357 | } 358 | inline const std::string& SentBody::_internal_key() const { 359 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 360 | return _impl_.key_.Get(); 361 | } 362 | inline void SentBody::_internal_set_key(const std::string& value) { 363 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 364 | ; 365 | _impl_.key_.Set(value, GetArenaForAllocation()); 366 | } 367 | inline std::string* SentBody::_internal_mutable_key() { 368 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 369 | ; 370 | return _impl_.key_.Mutable( GetArenaForAllocation()); 371 | } 372 | inline std::string* SentBody::release_key() { 373 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 374 | // @@protoc_insertion_point(field_release:com.chuzi.imsdk.server.model.proto.SentBody.key) 375 | return _impl_.key_.Release(); 376 | } 377 | inline void SentBody::set_allocated_key(std::string* value) { 378 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 379 | _impl_.key_.SetAllocated(value, GetArenaForAllocation()); 380 | #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING 381 | if (_impl_.key_.IsDefault()) { 382 | _impl_.key_.Set("", GetArenaForAllocation()); 383 | } 384 | #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING 385 | // @@protoc_insertion_point(field_set_allocated:com.chuzi.imsdk.server.model.proto.SentBody.key) 386 | } 387 | 388 | // int64 timestamp = 2; 389 | inline void SentBody::clear_timestamp() { 390 | _impl_.timestamp_ = ::int64_t{0}; 391 | } 392 | inline ::int64_t SentBody::timestamp() const { 393 | // @@protoc_insertion_point(field_get:com.chuzi.imsdk.server.model.proto.SentBody.timestamp) 394 | return _internal_timestamp(); 395 | } 396 | inline void SentBody::set_timestamp(::int64_t value) { 397 | _internal_set_timestamp(value); 398 | // @@protoc_insertion_point(field_set:com.chuzi.imsdk.server.model.proto.SentBody.timestamp) 399 | } 400 | inline ::int64_t SentBody::_internal_timestamp() const { 401 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 402 | return _impl_.timestamp_; 403 | } 404 | inline void SentBody::_internal_set_timestamp(::int64_t value) { 405 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 406 | ; 407 | _impl_.timestamp_ = value; 408 | } 409 | 410 | // map data = 3; 411 | inline int SentBody::_internal_data_size() const { 412 | return _internal_data().size(); 413 | } 414 | inline int SentBody::data_size() const { 415 | return _internal_data_size(); 416 | } 417 | inline void SentBody::clear_data() { 418 | _impl_.data_.Clear(); 419 | } 420 | inline const ::google::protobuf::Map& SentBody::_internal_data() const { 421 | PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); 422 | return _impl_.data_.GetMap(); 423 | } 424 | inline const ::google::protobuf::Map& SentBody::data() const { 425 | // @@protoc_insertion_point(field_map:com.chuzi.imsdk.server.model.proto.SentBody.data) 426 | return _internal_data(); 427 | } 428 | inline ::google::protobuf::Map* SentBody::_internal_mutable_data() { 429 | PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); 430 | return _impl_.data_.MutableMap(); 431 | } 432 | inline ::google::protobuf::Map* SentBody::mutable_data() { 433 | // @@protoc_insertion_point(field_mutable_map:com.chuzi.imsdk.server.model.proto.SentBody.data) 434 | return _internal_mutable_data(); 435 | } 436 | 437 | #ifdef __GNUC__ 438 | #pragma GCC diagnostic pop 439 | #endif // __GNUC__ 440 | 441 | // @@protoc_insertion_point(namespace_scope) 442 | } // namespace proto 443 | } // namespace model 444 | } // namespace server 445 | } // namespace imsdk 446 | } // namespace chuzi 447 | } // namespace com 448 | 449 | 450 | // @@protoc_insertion_point(global_scope) 451 | 452 | #include "google/protobuf/port_undef.inc" 453 | 454 | #endif // GOOGLE_PROTOBUF_INCLUDED_SentBody_2eproto_2epb_2eh 455 | -------------------------------------------------------------------------------- /src/provider/UserProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "UserProvider.h" 2 | 3 | #include 4 | 5 | UserProvider::UserProvider(QObject *parent) 6 | : QObject{parent} 7 | { 8 | 9 | } 10 | 11 | UserProvider::~UserProvider(){ 12 | 13 | } 14 | 15 | UserModel* UserProvider::loginUser(){ 16 | return of(IMManager::getInstance()->loginAccid()); 17 | } 18 | 19 | UserModel* UserProvider::of(const QString& uid){ 20 | for (int i = 0; i < _datas.size(); ++i) 21 | { 22 | auto item = _datas.at(i); 23 | if(!item.isNull() && item.get()->uid() == uid){ 24 | return item.get(); 25 | } 26 | } 27 | QSharedPointer userModel = QSharedPointer(new UserModel(this)); 28 | _datas.append(userModel); 29 | IMCallback *callback = new IMCallback(); 30 | connect(callback,&IMCallback::finish,this,[callback]{ callback->deleteLater(); }); 31 | connect(callback,&IMCallback::success,this,[callback,userModel](QJsonObject result){ 32 | auto user = result.value("data").toObject(); 33 | userModel->id(user.value("id").toString()); 34 | userModel->uid(user.value("uid").toString()); 35 | userModel->name(user.value("name").toString()); 36 | userModel->avatar(user.value("avatar").toString()); 37 | userModel->signature(user.value("signature").toString()); 38 | userModel->email(user.value("email").toString()); 39 | userModel->mobile(user.value("mobile").toString()); 40 | userModel->birthday(user.value("birthday").toDouble()); 41 | userModel->gender(user.value("gender").toInt()); 42 | userModel->extension(user.value("extension").toString()); 43 | }); 44 | IMManager::getInstance()->userInfo(uid,callback); 45 | return userModel.get(); 46 | } 47 | -------------------------------------------------------------------------------- /src/provider/UserProvider.h: -------------------------------------------------------------------------------- 1 | #ifndef USERPROVIDER_H 2 | #define USERPROVIDER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class UserProvider : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | SINGLETONG(UserProvider); 15 | explicit UserProvider(QObject *parent = nullptr); 16 | ~UserProvider(); 17 | Q_INVOKABLE UserModel* of(const QString& uid); 18 | Q_INVOKABLE UserModel* loginUser(); 19 | private: 20 | QList> _datas; 21 | }; 22 | 23 | #endif // USERPROVIDER_H 24 | -------------------------------------------------------------------------------- /src/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | res/qml/App.qml 4 | res/qml/component/AvatarView.qml 5 | res/qml/page/ContactsPage.qml 6 | res/qml/page/SessionPage.qml 7 | res/qml/window/LoginWindow.qml 8 | res/qml/window/MainWindow.qml 9 | res/qml/window/RegisterWindow.qml 10 | res/qml/window/SettingWindow.qml 11 | res/image/avatar_default.png 12 | res/qml/component/EmojiPanel.qml 13 | res/image/emoji/emoji_00.png 14 | res/image/emoji/emoji_01.png 15 | res/image/emoji/emoji_02.png 16 | res/image/emoji/emoji_03.png 17 | res/image/emoji/emoji_04.png 18 | res/image/emoji/emoji_05.png 19 | res/image/emoji/emoji_06.png 20 | res/image/emoji/emoji_07.png 21 | res/image/emoji/emoji_08.png 22 | res/image/emoji/emoji_09.png 23 | res/image/emoji/emoji_10.png 24 | res/image/emoji/emoji_11.png 25 | res/image/emoji/emoji_12.png 26 | res/image/emoji/emoji_13.png 27 | res/image/emoji/emoji_14.png 28 | res/image/emoji/emoji_15.png 29 | res/image/emoji/emoji_16.png 30 | res/image/emoji/emoji_17.png 31 | res/image/emoji/emoji_18.png 32 | res/image/emoji/emoji_19.png 33 | res/image/emoji/emoji_20.png 34 | res/image/emoji/emoji_21.png 35 | res/image/emoji/emoji_22.png 36 | res/image/emoji/emoji_23.png 37 | res/image/emoji/emoji_24.png 38 | res/image/emoji/emoji_25.png 39 | res/image/emoji/emoji_26.png 40 | res/image/emoji/emoji_27.png 41 | res/image/emoji/emoji_28.png 42 | res/image/emoji/emoji_29.png 43 | res/image/emoji/emoji_30.png 44 | res/image/emoji/emoji_31.png 45 | res/image/emoji/emoji_32.png 46 | res/image/emoji/emoji_33.png 47 | res/image/emoji/emoji_34.png 48 | res/image/emoji/emoji_35.png 49 | res/image/emoji/emoji_36.png 50 | res/image/emoji/emoji_37.png 51 | res/image/emoji/emoji_38.png 52 | res/image/emoji/emoji_39.png 53 | res/image/emoji/emoji_40.png 54 | res/image/emoji/emoji_41.png 55 | res/image/emoji/emoji_42.png 56 | res/image/emoji/emoji_43.png 57 | res/image/emoji/emoji_44.png 58 | res/image/emoji/emoji_45.png 59 | res/image/emoji/emoji_46.png 60 | res/image/emoji/emoji_47.png 61 | res/image/emoji/emoji_48.png 62 | res/image/emoji/emoji_49.png 63 | res/image/emoji/emoji_50.png 64 | res/image/emoji/emoji_51.png 65 | res/image/emoji/emoji_52.png 66 | res/image/emoji/emoji_53.png 67 | res/image/emoji/emoji_54.png 68 | res/image/emoji/emoji_55.png 69 | res/image/emoji/emoji_56.png 70 | res/image/emoji/emoji_57.png 71 | res/image/emoji/emoji_58.png 72 | res/image/emoji/emoji_59.png 73 | res/image/emoji/emoji_60.png 74 | res/image/emoji/emoji_61.png 75 | res/image/emoji/emoji_62.png 76 | res/image/emoji/emoji_63.png 77 | res/image/emoji/emoji_64.png 78 | res/image/emoji/emoji_65.png 79 | res/image/emoji/emoji_66.png 80 | res/image/emoji/emoji_67.png 81 | res/image/emoji/emoji_68.png 82 | res/qml/page/SearchPage.qml 83 | res/qml/window/FileSendWindow.qml 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/res/image/avatar_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/avatar_default.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_00.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_01.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_02.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_03.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_04.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_05.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_06.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_07.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_08.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_09.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_10.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_11.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_12.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_13.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_14.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_15.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_16.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_17.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_18.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_19.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_20.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_21.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_22.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_23.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_24.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_25.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_26.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_27.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_28.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_29.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_30.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_31.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_32.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_33.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_34.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_35.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_36.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_37.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_38.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_39.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_40.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_41.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_42.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_43.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_44.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_45.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_46.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_47.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_48.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_49.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_50.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_51.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_52.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_53.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_54.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_55.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_56.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_57.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_58.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_59.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_60.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_61.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_62.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_63.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_64.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_65.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_66.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_67.png -------------------------------------------------------------------------------- /src/res/image/emoji/emoji_68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzichu520/kim-qt/e6bad4e2a79380ffd836d4cd2582c03a2b6c86a4/src/res/image/emoji/emoji_68.png -------------------------------------------------------------------------------- /src/res/qml/App.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import FluentUI 1.0 3 | 4 | Item { 5 | id: app 6 | 7 | Component.onCompleted: { 8 | FluApp.init(app) 9 | FluApp.vsync = true 10 | FluApp.routes = { 11 | "/login":"qrc:/res/qml/window/LoginWindow.qml", 12 | "/register":"qrc:/res/qml/window/RegisterWindow.qml", 13 | "/setting":"qrc:/res/qml/window/SettingWindow.qml", 14 | "/fileSend":"qrc:/res/qml/window/FileSendWindow.qml", 15 | "/":"qrc:/res/qml/window/MainWindow.qml", 16 | } 17 | if(SettingsHelper.isLogin()){ 18 | FluApp.initialRoute = "/" 19 | }else{ 20 | FluApp.initialRoute = "/login" 21 | } 22 | FluApp.run() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/res/qml/component/AvatarView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import FluentUI 1.0 3 | 4 | FluClip { 5 | 6 | property var userInfo 7 | radius:[0,0,0,0] 8 | 9 | onUserInfoChanged: { 10 | if(userInfo){ 11 | image_source.source = Qt.binding(function(){ 12 | if(userInfo === null){ 13 | return "" 14 | } 15 | return userInfo.avatar 16 | }) 17 | } 18 | } 19 | 20 | Image{ 21 | anchors.fill: parent 22 | visible: Number(image_source.progress) !== 1 23 | source: "qrc:/res/image/avatar_default.png" 24 | } 25 | 26 | Image { 27 | id:image_source 28 | anchors.fill: parent 29 | mipmap: true 30 | cache: true 31 | visible: image_source.status === Image.Ready 32 | sourceSize: Qt.size(width*2,height*2) 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/res/qml/component/EmojiPanel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Window 2.15 3 | import QtQuick.Controls 2.15 4 | import FluentUI 1.0 5 | import IM 1.0 6 | 7 | Window{ 8 | id:control 9 | flags: Qt.FramelessWindowHint 10 | width: 460 11 | height: 320 12 | color: "#00000000" 13 | signal emojiClicked(string tag) 14 | onActiveFocusItemChanged: { 15 | if(!activeFocusItem){ 16 | close() 17 | } 18 | } 19 | 20 | EmoticonListModel{ 21 | id:emoticon_list_model 22 | } 23 | 24 | Page{ 25 | padding: 0 26 | anchors{ 27 | fill: parent 28 | margins: 10 29 | } 30 | background: FluArea{ 31 | radius: 5 32 | } 33 | FluShadow{ 34 | radius: 5 35 | } 36 | GridView{ 37 | clip: true 38 | cellWidth: 42 39 | cellHeight: 40 40 | boundsBehavior: GridView.StopAtBounds 41 | anchors{ 42 | fill: parent 43 | topMargin: 10 44 | bottomMargin: 10 45 | leftMargin: 12 46 | } 47 | model:emoticon_list_model 48 | delegate: FluIconButton{ 49 | width: 32 50 | height: 32 51 | verticalPadding: 0 52 | horizontalPadding: 0 53 | iconDelegate:Image{ 54 | width: 26 55 | height: 26 56 | source: "qrc:/res/image/emoji/"+model.display.file 57 | } 58 | text:model.display.tag.replace("[","").replace("]","") 59 | onClicked: { 60 | control.emojiClicked(model.display.tag) 61 | control.visible = false 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/res/qml/page/ContactsPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | import "../component" 8 | 9 | FluPage{ 10 | 11 | id:control 12 | launchMode: FluPageType.SingleInstance 13 | property var currentContact 14 | signal refreshFriends 15 | 16 | Component.onCompleted: { 17 | control.refreshFriends() 18 | } 19 | 20 | ContactListModel{ 21 | id:contact_model 22 | } 23 | 24 | IMCallback{ 25 | id:callback_user_search 26 | onStart: { 27 | layout_contact_find_empty.visible = false 28 | showLoading() 29 | } 30 | onFinish: { 31 | hideLoading() 32 | } 33 | onError: 34 | (code,message)=>{ 35 | showError(message) 36 | } 37 | onSuccess: 38 | (result)=>{ 39 | console.debug(JSON.stringify(result)) 40 | if(result.data){ 41 | loader_popup_user.userData = result.data 42 | loader_popup_user.sourceComponent = com_popup_user 43 | }else{ 44 | layout_contact_find_empty.visible = true 45 | } 46 | } 47 | } 48 | 49 | IMCallback{ 50 | id:callback_friend_remove 51 | onStart: { 52 | showLoading() 53 | } 54 | onFinish: { 55 | hideLoading() 56 | } 57 | onError: 58 | (code,message)=>{ 59 | showError(message) 60 | } 61 | onSuccess: 62 | (result)=>{ 63 | control.refreshFriends() 64 | } 65 | } 66 | 67 | onRefreshFriends: { 68 | contact_find_page.visible = false 69 | contact_model.resetData() 70 | // IMManager.friends(callback_friends) 71 | } 72 | 73 | FluMenu{ 74 | property string friendId 75 | id:menu_contact_item 76 | width: 100 77 | FluMenuItem{ 78 | text:"删除好友" 79 | onClicked: { 80 | IMManager.friendRemove(menu_contact_item.friendId,callback_friend_remove) 81 | } 82 | } 83 | function showMenu(id){ 84 | menu_contact_item.friendId = id 85 | menu_contact_item.popup() 86 | } 87 | } 88 | 89 | component ContactItem:Rectangle{ 90 | property bool selected: control.currentContact === display 91 | id:control_contact 92 | height: 65 93 | width: 250 94 | color:{ 95 | if(control_contact.selected){ 96 | return FluTheme.itemCheckColor 97 | } 98 | if(mouse_area_contact.containsMouse) 99 | return FluTheme.itemPressColor 100 | return FluTheme.itemNormalColor 101 | } 102 | MouseArea{ 103 | id:mouse_area_contact 104 | acceptedButtons: Qt.LeftButton|Qt.RightButton 105 | anchors.fill: parent 106 | hoverEnabled: true 107 | onClicked: 108 | (mouse)=>{ 109 | if(mouse.button === Qt.LeftButton){ 110 | control.currentContact = display 111 | }else{ 112 | menu_contact_item.showMenu(display.uid) 113 | } 114 | } 115 | } 116 | AvatarView{ 117 | id:item_avatar 118 | width: 42 119 | height: 42 120 | userInfo: display 121 | anchors{ 122 | verticalCenter: parent.verticalCenter 123 | left: parent.left 124 | leftMargin: 12 125 | } 126 | } 127 | FluText{ 128 | text:display.name 129 | anchors{ 130 | verticalCenter: parent.verticalCenter 131 | left: item_avatar.right 132 | leftMargin: 10 133 | } 134 | } 135 | } 136 | Item{ 137 | id:layout_contact 138 | width: 250 139 | height: parent.height 140 | Page{ 141 | background: Item{} 142 | visible: !contact_find_page.visible 143 | anchors.fill: parent 144 | Item{ 145 | id:layout_contact_top_bar 146 | width: parent.width 147 | height: 60 148 | FluTextBox{ 149 | id:textbox_search 150 | width: 200 151 | iconSource: FluentIcons.Search 152 | placeholderText: "搜索" 153 | anchors{ 154 | bottom: parent.bottom 155 | bottomMargin: 8 156 | left: parent.left 157 | leftMargin: 10 158 | } 159 | cleanEnabled: false 160 | rightPadding: 60 161 | FluIconButton{ 162 | iconSource: FluentIcons.Cancel 163 | iconSize: 12 164 | anchors{ 165 | right: parent.right 166 | rightMargin: 30 167 | verticalCenter: parent.verticalCenter 168 | } 169 | iconColor: FluTheme.dark ? Qt.rgba(222/255,222/255,222/255,1) : Qt.rgba(97/255,97/255,97/255,1) 170 | width: 30 171 | height: 20 172 | verticalPadding: 0 173 | horizontalPadding: 0 174 | visible: textbox_search.activeFocus 175 | onVisibleChanged: { 176 | if(!visible){ 177 | textbox_search.clear() 178 | } 179 | } 180 | onClicked:{ 181 | textbox_search.focus = false 182 | } 183 | } 184 | } 185 | FluIconButton{ 186 | width: 24 187 | height: 24 188 | iconSize: 14 189 | verticalPadding: 0 190 | horizontalPadding: 0 191 | iconSource: FluentIcons.Add 192 | anchors{ 193 | bottom: parent.bottom 194 | bottomMargin: 10 195 | right: parent.right 196 | rightMargin: 8 197 | } 198 | onClicked: { 199 | textbox_find_contact.clear() 200 | textbox_find_contact.forceActiveFocus() 201 | contact_find_page.visible = true 202 | } 203 | } 204 | } 205 | ListView{ 206 | id:list_contacts 207 | anchors{ 208 | left: parent.left 209 | right: parent.right 210 | top: layout_contact_top_bar.bottom 211 | bottom: parent.bottom 212 | } 213 | header:Item{ 214 | width:list_contacts.width 215 | height: 56 216 | FluButton{ 217 | text:"通讯录管理" 218 | anchors{ 219 | left: parent.left 220 | leftMargin: 10 221 | right: parent.right 222 | rightMargin: 10 223 | verticalCenter: parent.verticalCenter 224 | } 225 | onClicked: { 226 | showInfo("正在努力开发中...") 227 | } 228 | } 229 | } 230 | boundsBehavior: ListView.StopAtBounds 231 | model: contact_model 232 | delegate: ContactItem{} 233 | } 234 | Component{ 235 | id:com_search_page 236 | SearchPage{ 237 | } 238 | } 239 | FluLoader{ 240 | anchors{ 241 | top:layout_contact_top_bar.bottom 242 | left: parent.left 243 | right: parent.right 244 | bottom: parent.bottom 245 | } 246 | sourceComponent: textbox_search.activeFocus ? com_search_page : undefined 247 | } 248 | } 249 | Page{ 250 | id:contact_find_page 251 | anchors.fill: parent 252 | visible: false 253 | background: Item{} 254 | Item{ 255 | id:layout_contact_find_top_bar 256 | width: parent.width 257 | height: 60 258 | FluTextBox{ 259 | id:textbox_find_contact 260 | width: 200 261 | iconSource: FluentIcons.Search 262 | placeholderText: "账号/手机号" 263 | anchors{ 264 | bottom: parent.bottom 265 | bottomMargin: 8 266 | left: parent.left 267 | leftMargin: 10 268 | } 269 | onTextChanged: { 270 | layout_contact_find_empty.visible = false 271 | } 272 | } 273 | FluTextButton{ 274 | anchors{ 275 | bottom: parent.bottom 276 | bottomMargin: 8 277 | right: parent.right 278 | rightMargin: 2 279 | } 280 | text:"取消" 281 | font.pixelSize: 12 282 | onClicked: { 283 | contact_find_page.visible = false 284 | } 285 | } 286 | } 287 | Column{ 288 | spacing: 0 289 | width: parent.width 290 | anchors{ 291 | top: layout_contact_find_top_bar.bottom 292 | } 293 | Rectangle{ 294 | id:layout_contact_find_empty 295 | width: parent.width 296 | height: 60 297 | color: Qt.rgba(247/255,247/255,247/255,1) 298 | visible: false 299 | FluText{ 300 | color: FluTheme.fontSecondaryColor 301 | text:"无法找到该用户,请检查你填写的账号是否正确" 302 | wrapMode: Text.WrapAnywhere 303 | horizontalAlignment: Qt.AlignHCenter 304 | anchors{ 305 | left: parent.left 306 | right: parent.right 307 | leftMargin: 14 308 | rightMargin: 14 309 | verticalCenter: parent.verticalCenter 310 | } 311 | } 312 | } 313 | 314 | Item{ 315 | width: parent.width 316 | height: 60 317 | visible: textbox_find_contact.text !== "" 318 | Rectangle{ 319 | anchors.fill: parent 320 | color: { 321 | if(mouse_contact_find.containsPress){ 322 | return FluTheme.itemPressColor 323 | } 324 | if(mouse_contact_find.containsMouse){ 325 | return FluTheme.itemHoverColor 326 | } 327 | return FluTheme.itemNormalColor 328 | } 329 | } 330 | MouseArea{ 331 | id:mouse_contact_find 332 | anchors.fill: parent 333 | hoverEnabled: true 334 | onClicked: { 335 | IMManager.userSearch(textbox_find_contact.text,callback_user_search) 336 | } 337 | } 338 | RowLayout{ 339 | anchors.verticalCenter: parent.verticalCenter 340 | width: parent.width 341 | spacing: 0 342 | Rectangle{ 343 | Layout.preferredWidth: 36 344 | Layout.preferredHeight: 36 345 | Layout.alignment: Qt.AlignVCenter 346 | Layout.leftMargin: 14 347 | color: FluTheme.primaryColor 348 | radius: 4 349 | FluIcon{ 350 | iconSize: 20 351 | anchors.centerIn: parent 352 | iconSource: FluentIcons.Search 353 | iconColor: FluColors.White 354 | } 355 | } 356 | FluText{ 357 | text:"搜索: " 358 | Layout.leftMargin: 10 359 | } 360 | FluText{ 361 | text:textbox_find_contact.text 362 | color: FluTheme.primaryColor 363 | Layout.fillWidth: true 364 | elide: Text.ElideRight 365 | } 366 | FluIcon{ 367 | iconSource: FluentIcons.ChevronRight 368 | iconSize: 14 369 | Layout.rightMargin: 10 370 | } 371 | } 372 | } 373 | } 374 | FluDivider{ 375 | height: 1 376 | width: parent.width 377 | anchors.top: layout_contact_find_top_bar.bottom 378 | } 379 | } 380 | FluDivider{ 381 | height: 1 382 | width: parent.width 383 | anchors{ 384 | top: parent.top 385 | topMargin: 60 386 | } 387 | } 388 | } 389 | 390 | FluLoader{ 391 | property var userData 392 | id:loader_popup_user 393 | sourceComponent: userData ? com_popup_user : undefined 394 | } 395 | 396 | Component{ 397 | id:com_popup_user 398 | 399 | FluPopup{ 400 | id:popup_user 401 | property var user: userData.userInfo 402 | property bool isFriend: userData.isFriend 403 | width: 230 404 | height: 190 405 | modal: false 406 | anchors.centerIn: undefined 407 | x:255 408 | y:60 409 | visible: true 410 | onVisibleChanged: { 411 | if(!visible){ 412 | loader_popup_user.sourceComponent = undefined 413 | } 414 | } 415 | closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside 416 | contentItem: Item{ 417 | 418 | IMCallback{ 419 | id:callback_friend_add 420 | onStart: { 421 | showLoading() 422 | } 423 | onFinish: { 424 | hideLoading() 425 | } 426 | onError: 427 | (code,message)=>{ 428 | popup_user.close() 429 | showError(message) 430 | } 431 | onSuccess: 432 | (result)=>{ 433 | control.refreshFriends() 434 | popup_user.close() 435 | } 436 | } 437 | 438 | AvatarView{ 439 | id:popup_user_avatar 440 | width: 60 441 | height: 60 442 | userInfo: popup_user.user 443 | anchors{ 444 | top: parent.top 445 | left: parent.left 446 | topMargin: 20 447 | leftMargin: 20 448 | } 449 | } 450 | 451 | Column{ 452 | anchors{ 453 | left: popup_user_avatar.right 454 | top: popup_user_avatar.top 455 | leftMargin: 20 456 | topMargin: 4 457 | } 458 | FluText{ 459 | id:popup_user_name 460 | text: { 461 | if(popup_user.user){ 462 | return popup_user.user.name 463 | } 464 | return "" 465 | } 466 | } 467 | FluText{ 468 | id:popup_user_uid 469 | color : FluTheme.fontTertiaryColor 470 | text: { 471 | if(popup_user.user){ 472 | return "账号: " + popup_user.user.uid 473 | } 474 | return "" 475 | } 476 | } 477 | } 478 | 479 | Rectangle{ 480 | color: Qt.rgba(214/255,214/255,214/255,1) 481 | height: 1 482 | anchors{ 483 | top:parent.top 484 | topMargin: 100 485 | left: parent.left 486 | right: parent.right 487 | leftMargin: 14 488 | rightMargin: 14 489 | } 490 | } 491 | 492 | FluFilledButton{ 493 | text: popup_user.isFriend ? "发送聊天" : "添加好友" 494 | anchors{ 495 | horizontalCenter: parent.horizontalCenter 496 | bottom: parent.bottom 497 | bottomMargin: 26 498 | } 499 | onClicked:{ 500 | if(popup_user.isFriend){ 501 | showInfo("待开发") 502 | popup_user.close() 503 | }else{ 504 | IMManager.friendAdd(popup_user.user.uid,callback_friend_add) 505 | } 506 | } 507 | } 508 | } 509 | } 510 | } 511 | 512 | 513 | Component{ 514 | id:com_contact_info_panne 515 | Item{ 516 | id:layout_contact_info_panne 517 | 518 | Item{ 519 | width: 360 520 | height: parent.height 521 | anchors.horizontalCenter: parent.horizontalCenter 522 | 523 | AvatarView{ 524 | id:contact_info_avatar 525 | width: 60 526 | height: 60 527 | radius:[5,5,5,5] 528 | anchors{ 529 | top: parent.top 530 | left: parent.left 531 | topMargin: 120 532 | } 533 | userInfo: currentContact 534 | } 535 | 536 | ColumnLayout{ 537 | spacing: 0 538 | anchors{ 539 | top: contact_info_avatar.top 540 | left: contact_info_avatar.right 541 | leftMargin: 16 542 | } 543 | 544 | FluText{ 545 | text:currentContact.name 546 | 547 | } 548 | FluText{ 549 | text: "账号: %1".arg(currentContact.uid) 550 | color: FluTheme.fontTertiaryColor 551 | } 552 | } 553 | 554 | 555 | FluDivider{ 556 | id:contact_info_divider_1 557 | height: 1 558 | width: parent.width 559 | anchors{ 560 | top: contact_info_avatar.bottom 561 | topMargin: 20 562 | } 563 | } 564 | 565 | RowLayout{ 566 | anchors{ 567 | top: contact_info_divider_1.bottom 568 | topMargin: 30 569 | } 570 | 571 | FluIconButton{ 572 | iconSource:FluentIcons.Message 573 | text:"发消息" 574 | iconColor: Qt.rgba(123/255,138/255,171/255,1) 575 | textColor: iconColor 576 | display: Button.TextUnderIcon 577 | iconSize: 18 578 | font.pixelSize: 12 579 | onClicked: { 580 | IMManager.addEmptySession(currentContact.uid,0) 581 | MainEvent.switchSessionEvent(currentContact.uid) 582 | } 583 | } 584 | } 585 | } 586 | } 587 | } 588 | 589 | FluLoader{ 590 | anchors{ 591 | left: layout_contact.right 592 | top: parent.top 593 | bottom: parent.bottom 594 | right: parent.right 595 | } 596 | sourceComponent: control.currentContact ? com_contact_info_panne : undefined 597 | } 598 | 599 | FluDivider{ 600 | width: 1 601 | height: layout_contact.height 602 | orientation: Qt.Vertical 603 | anchors{ 604 | left: layout_contact.right 605 | } 606 | } 607 | 608 | 609 | } 610 | -------------------------------------------------------------------------------- /src/res/qml/page/SearchPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | import "../component" 8 | 9 | Page { 10 | background: Rectangle{ 11 | color: FluTheme.windowBackgroundColor 12 | } 13 | FluText{ 14 | anchors.centerIn: parent 15 | text:"正在努力开发中..." 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/res/qml/window/LoginWindow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | 8 | FluWindow { 9 | id:window 10 | width: 300 11 | height: 380 12 | showStayTop: false 13 | fixSize: true 14 | title: "KIM" 15 | 16 | property var registerPageRegister: registerForWindowResult("/register") 17 | property int pageIndex: 0 18 | 19 | component LoginPage:Page{ 20 | background: Rectangle{ 21 | color:window.backgroundColor 22 | } 23 | 24 | Connections{ 25 | target: registerPageRegister 26 | function onResult(data) 27 | { 28 | textbox_login_account.text = data.account 29 | textbox_login_password.text = data.password 30 | } 31 | } 32 | 33 | Component.onCompleted: { 34 | textbox_login_account.forceActiveFocus() 35 | } 36 | 37 | ColumnLayout{ 38 | anchors.centerIn: parent 39 | spacing: 0 40 | 41 | FluTextBox{ 42 | id:textbox_login_account 43 | Layout.preferredWidth: 240 44 | placeholderText: "请输入账号" 45 | } 46 | 47 | FluPasswordBox{ 48 | id:textbox_login_password 49 | Layout.topMargin: 20 50 | Layout.preferredWidth: 240 51 | placeholderText: "请输入密码" 52 | } 53 | 54 | FluFilledButton{ 55 | text: "登录" 56 | Layout.topMargin: 30 57 | Layout.preferredWidth: 240 58 | Layout.preferredHeight: 34 59 | onClicked: { 60 | var account = textbox_login_account.text 61 | var password = textbox_login_password.text 62 | IMManager.userLogin(account,password,callback_user_login) 63 | } 64 | } 65 | FluButton{ 66 | text: "注册" 67 | Layout.topMargin: 10 68 | Layout.preferredWidth: 240 69 | Layout.preferredHeight: 34 70 | onClicked: { 71 | registerPageRegister.launch() 72 | } 73 | } 74 | } 75 | FluTextButton{ 76 | text:"设置" 77 | anchors{ 78 | right: parent.right 79 | rightMargin: 10 80 | bottom: parent.bottom 81 | bottomMargin: 5 82 | } 83 | onClicked: { 84 | window.pageIndex = 1 85 | } 86 | } 87 | } 88 | 89 | component SettingPage:Page{ 90 | background: Rectangle{ 91 | color:window.backgroundColor 92 | } 93 | ColumnLayout{ 94 | anchors.centerIn: parent 95 | spacing: 20 96 | 97 | FluTextBox{ 98 | id:textbox_register_account 99 | Layout.preferredWidth: 240 100 | placeholderText: "Host" 101 | text:IMManager.host 102 | onTextChanged: { 103 | IMManager.host = text 104 | } 105 | } 106 | 107 | FluTextBox{ 108 | id:textbox_register_password 109 | Layout.preferredWidth: 240 110 | placeholderText: "WS Port" 111 | text: IMManager.wsport 112 | onTextChanged: { 113 | IMManager.wsport = text 114 | } 115 | } 116 | 117 | FluTextBox{ 118 | id:textbox_register_confirm_password 119 | Layout.preferredWidth: 240 120 | placeholderText: "Api Port" 121 | text: IMManager.port 122 | onTextChanged: { 123 | IMManager.port = text 124 | } 125 | } 126 | } 127 | FluTextButton{ 128 | text:"返回登录" 129 | anchors{ 130 | right: parent.right 131 | rightMargin: 10 132 | bottom: parent.bottom 133 | bottomMargin: 5 134 | } 135 | onClicked: { 136 | window.pageIndex = 0 137 | } 138 | } 139 | } 140 | 141 | IMCallback{ 142 | id:callback_user_login 143 | onStart: { 144 | showLoading() 145 | } 146 | onFinish: { 147 | hideLoading() 148 | } 149 | onError: 150 | (code,message)=>{ 151 | showError(message) 152 | } 153 | onSuccess: 154 | (result)=>{ 155 | console.debug(JSON.stringify(result)) 156 | SettingsHelper.login(result.data.uid,result.token) 157 | // SettingsHelper.saveToken(result.token) 158 | FluApp.navigate("/") 159 | window.close() 160 | } 161 | } 162 | 163 | SwipeView{ 164 | id:swipe_view 165 | anchors.fill: parent 166 | interactive: false 167 | currentIndex: window.pageIndex 168 | LoginPage{ 169 | 170 | } 171 | SettingPage{ 172 | 173 | } 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/res/qml/window/MainWindow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | import "../component" 8 | 9 | FluWindow { 10 | id:window 11 | width: 880 12 | height: 580 13 | showStayTop: false 14 | title: "KIM" 15 | minimumWidth: 702 16 | minimumHeight: 500 17 | property var loginUser : UserProvider.loginUser() 18 | fitsAppBarWindows: true 19 | appBar: FluAppBar { 20 | width: window.width 21 | height: 30 22 | darkText: "夜间模式" 23 | showDark: true 24 | darkClickListener:(button)=>handleDarkChanged(button) 25 | closeClickListener: ()=>{window.close()} 26 | z:7 27 | } 28 | 29 | Component.onCompleted: { 30 | IMManager.wsConnect() 31 | } 32 | 33 | Connections{ 34 | target: IMManager 35 | function onWsConnected(){ 36 | loginUser = UserProvider.loginUser() 37 | } 38 | } 39 | 40 | Connections{ 41 | target: MainEvent 42 | function onSwitchSessionEvent(uid){ 43 | nav_view.startPageByItem(pane_item_session) 44 | } 45 | } 46 | 47 | FluObject{ 48 | id:items_original 49 | FluPaneItem{ 50 | id:pane_item_session 51 | count: 99 52 | title: "聊天" 53 | icon:FluentIcons.Home 54 | url:"qrc:/res/qml/page/SessionPage.qml" 55 | onTap:{ 56 | nav_view.push(url) 57 | } 58 | } 59 | FluPaneItem{ 60 | id:pane_item_contacts 61 | count: 99 62 | title: "联系人" 63 | icon:FluentIcons.ContactPresence 64 | url:"qrc:/res/qml/page/ContactsPage.qml" 65 | onTap:{ 66 | nav_view.push(url) 67 | } 68 | } 69 | } 70 | 71 | FluObject{ 72 | id:items_footer 73 | FluPaneItem{ 74 | title:"设置" 75 | icon:FluentIcons.Settings 76 | onTapListener:function(){ 77 | FluApp.navigate("/setting") 78 | } 79 | } 80 | } 81 | 82 | 83 | FluNavigationView{ 84 | id:nav_view 85 | width: parent.width 86 | height: parent.height 87 | pageMode: FluNavigationViewType.Stack 88 | items: items_original 89 | navCompactWidth: 60 90 | footerItems:items_footer 91 | hideNavAppBar: true 92 | navTopMargin: 86 93 | displayMode:FluNavigationViewType.Compact 94 | logo: UserProvider.loginUser().avatar 95 | title: UserProvider.loginUser().name 96 | Component.onCompleted: { 97 | setCurrentIndex(0) 98 | } 99 | } 100 | 101 | AvatarView{ 102 | width: 38 103 | height: 38 104 | userInfo: loginUser 105 | anchors{ 106 | left: parent.left 107 | leftMargin: (nav_view.navCompactWidth - width) / 2 108 | top: parent.top 109 | topMargin: 36 110 | } 111 | } 112 | 113 | Component{ 114 | id:com_reveal 115 | CircularReveal{ 116 | id:reveal 117 | target:window.contentItem 118 | anchors.fill: parent 119 | onAnimationFinished:{ 120 | loader_reveal.sourceComponent = undefined 121 | } 122 | onImageChanged: { 123 | changeDark() 124 | } 125 | } 126 | } 127 | 128 | FluLoader{ 129 | id:loader_reveal 130 | anchors.fill: parent 131 | } 132 | 133 | function distance(x1,y1,x2,y2){ 134 | return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) 135 | } 136 | 137 | function handleDarkChanged(button){ 138 | if(!FluTheme.enableAnimation){ 139 | changeDark() 140 | }else{ 141 | loader_reveal.sourceComponent = com_reveal 142 | var target = window.contentItem 143 | var pos = button.mapToItem(target,0,0) 144 | var mouseX = pos.x 145 | var mouseY = pos.y 146 | var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height)) 147 | var reveal = loader_reveal.item 148 | reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius) 149 | } 150 | } 151 | 152 | function changeDark(){ 153 | if(FluTheme.dark){ 154 | FluTheme.darkMode = FluThemeType.Light 155 | }else{ 156 | FluTheme.darkMode = FluThemeType.Dark 157 | } 158 | } 159 | 160 | Window{ 161 | flags: Qt.FramelessWindowHint 162 | width: 330 163 | height: 34 164 | visible: IMManager.netStatus === 2 165 | color: Qt.rgba(204/255,83/255,83/255,1) 166 | x:window.x + (window.width - width)/2 167 | y:Math.max(window.y - height - 5,0) 168 | Row{ 169 | anchors.centerIn: parent 170 | Text{ 171 | text:"网络不可用, 请检查你的网络设置" 172 | color: FluColors.White 173 | font.pixelSize: 15 174 | } 175 | } 176 | } 177 | 178 | } 179 | -------------------------------------------------------------------------------- /src/res/qml/window/RegisterWindow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | 8 | FluWindow { 9 | id:window 10 | width: 480 11 | height: 640 12 | showStayTop: false 13 | fixSize: true 14 | title: "账号注册" 15 | modality: Qt.ApplicationModal 16 | 17 | component MustItem:Row{ 18 | spacing: 8 19 | Text{ 20 | text:"*" 21 | color: "red" 22 | anchors.verticalCenter: parent.verticalCenter 23 | } 24 | } 25 | 26 | Component.onCompleted: { 27 | textbox_register_account.forceActiveFocus() 28 | } 29 | 30 | FluText{ 31 | font.pixelSize: 20 32 | font.weight: Font.Medium 33 | text:"欢迎注册KIM" 34 | anchors{ 35 | horizontalCenter: parent.horizontalCenter 36 | top: parent.top 37 | topMargin: 20 38 | } 39 | } 40 | 41 | ColumnLayout{ 42 | anchors.centerIn: parent 43 | spacing: 20 44 | 45 | MustItem{ 46 | FluTextBox{ 47 | id:textbox_register_account 48 | Layout.preferredWidth: 240 49 | placeholderText: "请输入账号" 50 | } 51 | } 52 | MustItem{ 53 | FluPasswordBox{ 54 | id:textbox_register_password 55 | Layout.preferredWidth: 240 56 | placeholderText: "请输入密码" 57 | } 58 | } 59 | 60 | MustItem{ 61 | FluPasswordBox{ 62 | id:textbox_register_confirm_password 63 | Layout.preferredWidth: 240 64 | placeholderText: "请再次输入密码" 65 | } 66 | } 67 | 68 | MustItem{ 69 | FluTextBox{ 70 | id:textbox_register_name 71 | Layout.preferredWidth: 240 72 | placeholderText: "请输入姓名" 73 | } 74 | } 75 | 76 | FluTextBox{ 77 | id:textbox_register_mobile 78 | Layout.preferredWidth: 240 79 | placeholderText: "请输入手机号" 80 | Layout.alignment: Qt.AlignRight 81 | } 82 | 83 | FluTextBox{ 84 | id:textbox_register_email 85 | Layout.preferredWidth: 240 86 | placeholderText: "请输入邮箱" 87 | Layout.alignment: Qt.AlignRight 88 | } 89 | 90 | FluCalendarPicker{ 91 | id:picker_birthday 92 | text:"您的出生年月" 93 | Layout.leftMargin: 12 94 | } 95 | 96 | Row{ 97 | spacing: 12 98 | Layout.leftMargin: 12 99 | FluText{ 100 | text:"选择您的头像" 101 | anchors.verticalCenter: parent.verticalCenter 102 | } 103 | FluClip{ 104 | anchors.verticalCenter: parent.verticalCenter 105 | width: 40 106 | height: 40 107 | radius: [20,20,20,20] 108 | Image{ 109 | anchors.fill: parent 110 | source: "https://zhu-zichu.gitee.io/default.png" 111 | } 112 | MouseArea{ 113 | anchors.fill: parent 114 | cursorShape: Qt.PointingHandCursor 115 | onClicked: { 116 | showInfo("敬请期待") 117 | } 118 | } 119 | } 120 | } 121 | 122 | FluFilledButton{ 123 | text: "注册" 124 | Layout.preferredHeight: 34 125 | Layout.topMargin: 10 126 | Layout.fillWidth: true 127 | onClicked: { 128 | var account = textbox_register_account.text 129 | var password = textbox_register_password.text 130 | var confirmPassword = textbox_register_confirm_password.text 131 | var name = textbox_register_name.text 132 | var mobile = textbox_register_mobile.text 133 | var email = textbox_register_email.text 134 | var birthday 135 | if(picker_birthday.current){ 136 | birthday = picker_birthday.current.valueOf() 137 | }else{ 138 | birthday = 0 139 | } 140 | var avatar = "https://zhu-zichu.gitee.io/default.png" 141 | IMManager.userRegister(account,password,confirmPassword,name,mobile,email,birthday,avatar,callback_user_register) 142 | } 143 | } 144 | } 145 | 146 | 147 | 148 | IMCallback{ 149 | id:callback_user_register 150 | onStart: { 151 | showLoading() 152 | } 153 | onFinish: { 154 | hideLoading() 155 | } 156 | onError: 157 | (code,message)=>{ 158 | showError(message) 159 | } 160 | onSuccess: 161 | (result)=>{ 162 | showSuccess("注册成功") 163 | onResult({account:textbox_register_account.text,password:textbox_register_password.text}) 164 | window.close() 165 | } 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/res/qml/window/SettingWindow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.15 2 | import QtQuick.Layouts 1.15 3 | import QtQuick.Controls 2.15 4 | import QtQuick.Window 2.15 5 | import FluentUI 1.0 6 | import IM 1.0 7 | import "../component" 8 | 9 | FluWindow { 10 | id:window 11 | width: 560 12 | height: 480 13 | showStayTop: false 14 | fixSize: true 15 | title: "设置" 16 | launchMode: FluWindowType.SingleTask 17 | 18 | component TabItem:Item{ 19 | property bool selected: listview_tab.currentIndex === model.index 20 | width: listview_tab.width 21 | height: 30 22 | FluText{ 23 | anchors.centerIn: parent 24 | text:model.title 25 | color: selected ? FluTheme.primaryColor : textColor 26 | } 27 | TapHandler{ 28 | onTapped: { 29 | listview_tab.currentIndex = model.index 30 | } 31 | } 32 | } 33 | 34 | ListModel{ 35 | id:listmodel_tab 36 | ListElement{ 37 | title:"账号设置" 38 | comId: function(){return com_account_settings} 39 | } 40 | // ListElement{ 41 | // title:"关于KIM" 42 | // comId: function(){return com_about} 43 | // } 44 | } 45 | 46 | ListView{ 47 | id:listview_tab 48 | currentIndex: 0 49 | width: 100 50 | anchors{ 51 | top: parent.top 52 | topMargin: 50 53 | left: parent.left 54 | bottom: parent.bottom 55 | } 56 | model:listmodel_tab 57 | delegate: TabItem{} 58 | } 59 | 60 | FluDivider{ 61 | width: 1 62 | anchors{ 63 | top: listview_tab.top 64 | right: listview_tab.right 65 | bottom: parent.bottom 66 | } 67 | orientation: Qt.Vertical 68 | } 69 | 70 | Component{ 71 | id:com_account_settings 72 | Item{ 73 | Component{ 74 | id:com_profile_panne 75 | FluArea{ 76 | 77 | property var user : UserProvider.loginUser() 78 | 79 | AvatarView{ 80 | id: profile_avatar 81 | width: 50 82 | height: 50 83 | userInfo: user 84 | anchors{ 85 | left: parent.left 86 | leftMargin: 30 87 | verticalCenter: parent.verticalCenter 88 | } 89 | } 90 | 91 | FluText{ 92 | text:user.name 93 | font.pixelSize: 20 94 | anchors{ 95 | left: profile_avatar.right 96 | top: profile_avatar.top 97 | leftMargin: 15 98 | topMargin: 2 99 | } 100 | } 101 | 102 | FluText{ 103 | text: "账号:%1".arg(user.uid) 104 | font.pixelSize: 11 105 | color: FluTheme.fontTertiaryColor 106 | anchors{ 107 | left: profile_avatar.right 108 | bottom: profile_avatar.bottom 109 | leftMargin: 15 110 | bottomMargin: 2 111 | } 112 | } 113 | } 114 | } 115 | 116 | FluLoader{ 117 | height: 140 118 | width: parent.width 119 | sourceComponent: com_profile_panne 120 | } 121 | 122 | FluFilledButton{ 123 | text:"退出登录" 124 | anchors{ 125 | horizontalCenter: parent.horizontalCenter 126 | bottom: parent.bottom 127 | bottomMargin: 20 128 | } 129 | onClicked: { 130 | dialog_logout.open() 131 | } 132 | } 133 | } 134 | } 135 | 136 | Component{ 137 | id:com_about 138 | Item{ 139 | FluArea{ 140 | height: 250 141 | width: parent.width 142 | } 143 | } 144 | } 145 | 146 | FluLoader{ 147 | sourceComponent: listmodel_tab.get(listview_tab.currentIndex).comId() 148 | anchors{ 149 | left: listview_tab.right 150 | leftMargin: 48 151 | right: parent.right 152 | rightMargin: 48 153 | top: listview_tab.top 154 | bottom: parent.bottom 155 | bottomMargin: 40 156 | } 157 | } 158 | 159 | FluContentDialog{ 160 | id:dialog_logout 161 | title:"友情提示" 162 | message:"退出登录后将无法收到新消息,确定退出登录?" 163 | buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton 164 | negativeText: "取消" 165 | positiveText:"确定" 166 | onPositiveClicked:{ 167 | showLoading() 168 | SettingsHelper.logout() 169 | delay_restart.restart() 170 | } 171 | } 172 | 173 | Timer{ 174 | id:delay_restart 175 | interval: 300 176 | onTriggered: { 177 | FluApp.exit(931) 178 | } 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETON_H 2 | #define SINGLETON_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | class Singleton { 11 | public: 12 | static T* getInstance(); 13 | 14 | Singleton(const Singleton& other) = delete; 15 | Singleton& operator=(const Singleton& other) = delete; 16 | 17 | private: 18 | static std::mutex mutex; 19 | static T* instance; 20 | }; 21 | 22 | template 23 | std::mutex Singleton::mutex; 24 | template 25 | T* Singleton::instance; 26 | template 27 | T* Singleton::getInstance() { 28 | if (instance == nullptr) { 29 | std::lock_guard locker(mutex); 30 | if (instance == nullptr) { 31 | instance = new T(); 32 | } 33 | } 34 | return instance; 35 | } 36 | 37 | #define SINGLETONG(Class) \ 38 | private: \ 39 | friend class Singleton; \ 40 | friend struct QScopedPointerDeleter; \ 41 | \ 42 | public: \ 43 | static Class* getInstance() { \ 44 | return Singleton::getInstance(); \ 45 | } 46 | 47 | #endif // SINGLETON_H 48 | -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #define Q_PROPERTY_AUTO(TYPE, M) \ 5 | Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed) \ 6 | public: \ 7 | Q_SIGNAL void M##Changed(); \ 8 | void M(TYPE in_##M) \ 9 | { \ 10 | _##M = in_##M; \ 11 | Q_EMIT M##Changed(); \ 12 | } \ 13 | TYPE M() \ 14 | { \ 15 | return _##M; \ 16 | } \ 17 | \ 18 | public: \ 19 | TYPE _##M; 20 | 21 | #endif // STDAFX_H 22 | --------------------------------------------------------------------------------