mirror of
https://github.com/jie65535/IM.git
synced 2024-07-27 19:05:11 +08:00
提交源码
This commit is contained in:
parent
a280783e7f
commit
f029404192
BIN
IM Porject/IM.mp4
Normal file
BIN
IM Porject/IM.mp4
Normal file
Binary file not shown.
51
IM Porject/IM/IM.pro
Normal file
51
IM Porject/IM/IM.pro
Normal file
@ -0,0 +1,51 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-11-30T17:54:04
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui network sql
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = IM
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
imclient.cpp \
|
||||
formlogin.cpp \
|
||||
imdal.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
imclient.h \
|
||||
protocol.h \
|
||||
formlogin.h \
|
||||
immessage.h \
|
||||
imdal.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
formlogin.ui
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
322
IM Porject/IM/IM.pro.user
Normal file
322
IM Porject/IM/IM.pro.user
Normal file
@ -0,0 +1,322 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.7.2, 2018-12-08T20:06:10. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{2d03fc4c-541a-4fa5-8f5c-ae92a1998dce}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
|
||||
<value type="QString">-fno-delayed-template-parsing</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.11.2 MinGW 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.11.2 MinGW 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5112.win32_mingw53_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IM-Desktop_Qt_5_11_2_MinGW_32bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IM-Desktop_Qt_5_11_2_MinGW_32bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IM-Desktop_Qt_5_11_2_MinGW_32bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">IM</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/C++/Qt/IM/IM.pro</value>
|
||||
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">IM.pro</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">E:/C++/Qt/build-IM-Desktop_Qt_5_11_2_MinGW_32bit-Debug</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
128
IM Porject/IM/formlogin.cpp
Normal file
128
IM Porject/IM/formlogin.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "formlogin.h"
|
||||
#include "ui_formlogin.h"
|
||||
#include <QMessageBox>
|
||||
#include "mainwindow.h"
|
||||
|
||||
FormLogin::FormLogin(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::FormLogin)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(IMClient::instance(), &IMClient::serverConnected, this, &FormLogin::serverConnected);
|
||||
connect(IMClient::instance(), &IMClient::serverClose, this, &FormLogin::serverClose);
|
||||
connect(IMClient::instance(), &IMClient::loginResult, this, &FormLogin::loginResult);
|
||||
connect(IMClient::instance(), &IMClient::connectError, this, &FormLogin::connectError);
|
||||
// 连接服务器
|
||||
IMClient::instance()->connectServer(ui->leHostName->text().trimmed());
|
||||
}
|
||||
|
||||
FormLogin::~FormLogin()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// 连接成功后将重试按钮什么的隐藏掉
|
||||
void FormLogin::serverConnected()
|
||||
{
|
||||
ui->lblServerConnectState->clear();
|
||||
ui->btnRetry->setHidden(true);
|
||||
ui->leHostName->setHidden(true);
|
||||
}
|
||||
|
||||
// 如果服务器关闭,那么程序跟着关闭
|
||||
void FormLogin::serverClose()
|
||||
{
|
||||
QMessageBox::warning(this, "警告", "服务器已关闭,程序即将退出!");
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
// 如果连接发生错误,提示并将重试按钮显示
|
||||
void FormLogin::connectError(QString ErrorInfo)
|
||||
{
|
||||
QMessageBox::critical(this, "连接失败", "错误信息:" + ErrorInfo);
|
||||
ui->lblServerConnectState->setText("服务器连接失败!");
|
||||
ui->btnRetry->setHidden(false);
|
||||
ui->leHostName->setHidden(false);
|
||||
}
|
||||
|
||||
// 当登录有结果时
|
||||
void FormLogin::loginResult(bool isSuccess)
|
||||
{
|
||||
// 如果登录没有成功,将登录按钮设置为可用,并提示用户
|
||||
if (!isSuccess)
|
||||
{
|
||||
QMessageBox::critical(this, "登录失败", "该用户名或连接已经登录!");
|
||||
ui->btnLogin->setText("登 录");
|
||||
ui->btnLogin->setEnabled(true);
|
||||
ui->lineEdit->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
// 登录成功,启动主窗体
|
||||
MainWindow *w = new MainWindow;
|
||||
w->show();
|
||||
this->close();
|
||||
}
|
||||
|
||||
// 登录按钮按下时
|
||||
void FormLogin::on_btnLogin_clicked()
|
||||
{
|
||||
// 获取用户名
|
||||
QString username = ui->lineEdit->text().trimmed();
|
||||
if (username.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, "错误", "请输入用户名!");
|
||||
return;
|
||||
}
|
||||
// 检测是否存在非法字符
|
||||
bool isSpace = false;
|
||||
for (int i = 0; i < username.length(); ++i)
|
||||
{
|
||||
if (username[i].isSpace()
|
||||
|| username[i] == ':'
|
||||
|| username[i] == '"'
|
||||
|| username[i] == '/'
|
||||
|| username[i] == '*'
|
||||
|| username[i] == '|'
|
||||
|| username[i] == '?'
|
||||
|| username[i] == '<'
|
||||
|| username[i] == '>')
|
||||
{
|
||||
isSpace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSpace)
|
||||
{
|
||||
QMessageBox::critical(this, "错误", "用户名中有非法字符!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IMClient::instance()->isOpen())
|
||||
{
|
||||
QMessageBox::critical(this, "错误", "未连接服务器!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试登录
|
||||
IMClient::instance()->login(username);
|
||||
ui->btnLogin->setText("登录中...");
|
||||
ui->btnLogin->setEnabled(false);
|
||||
ui->lineEdit->setEnabled(false);
|
||||
}
|
||||
|
||||
// 当重试按钮按下时
|
||||
void FormLogin::on_btnRetry_clicked()
|
||||
{
|
||||
// 如果连接已经打开了,就直接隐藏按钮
|
||||
if (IMClient::instance()->isOpen())
|
||||
{
|
||||
ui->lblServerConnectState->clear();
|
||||
ui->btnRetry->setHidden(true);
|
||||
ui->leHostName->setHidden(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 否则尝试重新连接服务器
|
||||
IMClient::instance()->connectServer(ui->leHostName->text().trimmed());
|
||||
}
|
||||
}
|
39
IM Porject/IM/formlogin.h
Normal file
39
IM Porject/IM/formlogin.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef FORMLOGIN_H
|
||||
#define FORMLOGIN_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class FormLogin;
|
||||
}
|
||||
|
||||
class FormLogin : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormLogin(QWidget *parent = nullptr);
|
||||
~FormLogin();
|
||||
// 槽
|
||||
private slots:
|
||||
// 服务器连接成功时触发
|
||||
void serverConnected();
|
||||
// 服务器关闭时触发
|
||||
void serverClose();
|
||||
// 连接发生错误时触发
|
||||
void connectError(QString ErrorInfo);
|
||||
|
||||
// 登录结果
|
||||
// 参数:isSuccess 是否登录成功
|
||||
void loginResult(bool isSuccess);
|
||||
|
||||
|
||||
void on_btnLogin_clicked();
|
||||
|
||||
void on_btnRetry_clicked();
|
||||
|
||||
private:
|
||||
Ui::FormLogin *ui;
|
||||
};
|
||||
|
||||
#endif // FORMLOGIN_H
|
130
IM Porject/IM/formlogin.ui
Normal file
130
IM Porject/IM/formlogin.ui
Normal file
@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FormLogin</class>
|
||||
<widget class="QWidget" name="FormLogin">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>IM</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>120</y>
|
||||
<width>41</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>用户名:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnLogin">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>170</y>
|
||||
<width>181</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>登 录</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lblServerConnectState">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>280</y>
|
||||
<width>131</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>服务器连接状态:未连接</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnRetry">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>280</y>
|
||||
<width>41</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>重试</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>40</y>
|
||||
<width>31</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IM</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>120</y>
|
||||
<width>151</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="leHostName">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>190</x>
|
||||
<y>280</y>
|
||||
<width>151</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>127.0.0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
BIN
IM Porject/IM/images/group.png
Normal file
BIN
IM Porject/IM/images/group.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
BIN
IM Porject/IM/images/userOffline.png
Normal file
BIN
IM Porject/IM/images/userOffline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
IM Porject/IM/images/userOnline.png
Normal file
BIN
IM Porject/IM/images/userOnline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
223
IM Porject/IM/imclient.cpp
Normal file
223
IM Porject/IM/imclient.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
#include <QDateTime>
|
||||
#include "imclient.h"
|
||||
#include "protocol.h"
|
||||
#include "imdal.h"
|
||||
|
||||
IMClient::IMClient(QObject *parent)
|
||||
: QObject(parent),
|
||||
m_socket(new QTcpSocket)
|
||||
{
|
||||
connect(m_socket, &QTcpSocket::connected, this, &IMClient::connected);
|
||||
connect(m_socket, &QTcpSocket::readyRead, this, &IMClient::readyread);
|
||||
connect(m_socket, &QTcpSocket::disconnected, this, &IMClient::disconnected);
|
||||
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
|
||||
[this](QAbstractSocket::SocketError socketError){this->error(socketError);});
|
||||
}
|
||||
|
||||
IMClient *IMClient::instance()
|
||||
{
|
||||
static IMClient imClient;
|
||||
return &imClient;
|
||||
}
|
||||
|
||||
IMClient::~IMClient()
|
||||
{
|
||||
qDebug() << "~IMClient";
|
||||
if (m_socket != nullptr)
|
||||
{
|
||||
m_socket->close();
|
||||
delete m_socket;
|
||||
}
|
||||
}
|
||||
|
||||
// 连接服务器
|
||||
void IMClient::connectServer(QString hostName)
|
||||
{
|
||||
m_socket->connectToHost(hostName, 9876, QTcpSocket::ReadWrite);
|
||||
}
|
||||
|
||||
// 登录
|
||||
void IMClient::login(QString name)
|
||||
{
|
||||
this->m_name = name;
|
||||
this->sendData(QString("%1 %2").arg(ClientFunctionCode::Login).arg(name));
|
||||
}
|
||||
|
||||
// 发送私聊消息
|
||||
void IMClient::sendPrivateMessage(QString toName, QString content)
|
||||
{
|
||||
// 发送消息到服务器
|
||||
this->sendData(QString("%1 %2 %3").arg(ClientFunctionCode::SendPrivateMessage).arg(toName).arg(content));
|
||||
// 构造消息对象,用o表示是发出消息
|
||||
IMMessage msg("o", content, QDateTime::currentDateTime());
|
||||
// 将消息添加到聊天记录中
|
||||
this->m_chatRecord[toName].append(msg);
|
||||
// 将消息插入到数据库中
|
||||
IMDAL::instance()->addPrivateMessage(toName, msg);
|
||||
}
|
||||
|
||||
// 发送群聊消息
|
||||
void IMClient::sendGroupMessage(QString content)
|
||||
{
|
||||
// 发送消息到服务器
|
||||
this->sendData(QString("%1 %2").arg(ClientFunctionCode::SendGroupMessage).arg(content));
|
||||
// 构造消息对象
|
||||
IMMessage msg(this->m_name, content, QDateTime::currentDateTime());
|
||||
// 将消息添加到聊天记录中
|
||||
this->m_gruopChatRecord.append(msg);
|
||||
// 将消息插入到数据库中
|
||||
IMDAL::instance()->addGroupMessage(msg);
|
||||
}
|
||||
|
||||
const QVector<IMMessage> *IMClient::getChatRecord(QString name)
|
||||
{
|
||||
if (!this->m_chatRecord.contains(name))
|
||||
this->m_chatRecord[name] = IMDAL::instance()->getPrivateMessage(name);
|
||||
|
||||
return &this->m_chatRecord[name];
|
||||
}
|
||||
|
||||
// 连接成功时触发
|
||||
void IMClient::connected()
|
||||
{
|
||||
qDebug() << "connected";
|
||||
emit serverConnected();
|
||||
}
|
||||
|
||||
// 当接收到数据时触发
|
||||
void IMClient::readyread()
|
||||
{
|
||||
// 获取接收到数据的对象
|
||||
QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
|
||||
// 获取数据
|
||||
QByteArray data = sender->readAll();
|
||||
QTextStream in(data, QIODevice::ReadOnly);
|
||||
qDebug() << "readyread:" << data;
|
||||
|
||||
// 进行协议分析与任务调度
|
||||
int functionID = 0;
|
||||
in >> functionID;
|
||||
switch (functionID) {
|
||||
case ServerFunctionCode::PrivateMessage:
|
||||
{
|
||||
// 如果是私聊消息,获取发送者昵称,然后发出获取到私聊消息的信号
|
||||
QString fromName;
|
||||
in >> fromName;
|
||||
in.seek(in.pos() + 1);
|
||||
// 构造一个消息对象,发送者用'i'表示是接受到的消息
|
||||
IMMessage msg("i", in.readAll(), QDateTime::currentDateTime());
|
||||
// 将它添加到聊天记录中
|
||||
this->m_chatRecord[fromName].append(msg);
|
||||
// 并且插入数据库
|
||||
IMDAL::instance()->addPrivateMessage(fromName, msg);
|
||||
// 然后将发送者改回原来的名称
|
||||
msg.fromName = fromName;
|
||||
// 通过信号将其传递出去
|
||||
emit receivedPrivateMessage(msg);
|
||||
}break;
|
||||
case ServerFunctionCode::GroupMessage:
|
||||
{
|
||||
// 如果是群聊消息,获取发送者昵称,然后发出获取到群聊消息的信号
|
||||
QString fromName;
|
||||
in >> fromName;
|
||||
in.seek(in.pos() + 1);
|
||||
// 构造一个消息对象
|
||||
IMMessage msg(fromName, in.readAll(), QDateTime::currentDateTime());
|
||||
// 添加到聊天记录中
|
||||
this->m_gruopChatRecord.append(msg);
|
||||
// 添加到数据库中
|
||||
IMDAL::instance()->addGroupMessage(msg);
|
||||
// 发出信号
|
||||
emit receivedGroupMessage(msg);
|
||||
}break;
|
||||
case ServerFunctionCode::UserOnline:
|
||||
{
|
||||
// 如果是用户上线,获取发送者昵称,然后发出用户上线信号
|
||||
QString fromName;
|
||||
in >> fromName;
|
||||
if (m_offline.contains(fromName))
|
||||
m_offline.removeOne(fromName);
|
||||
m_online.append(fromName);
|
||||
emit userOnline(fromName);
|
||||
}break;
|
||||
case ServerFunctionCode::UserOffline:
|
||||
{
|
||||
// 如果是用户下线,获取发送者昵称,然后发出用户下线信号
|
||||
QString fromName;
|
||||
in >> fromName;
|
||||
if (m_online.contains(fromName))
|
||||
m_online.removeOne(fromName);
|
||||
m_offline.append(fromName);
|
||||
emit userOffline(fromName);
|
||||
}break;
|
||||
case ServerFunctionCode::LoginResult:
|
||||
{
|
||||
// 如果是登录有结果了,先获取登录结果
|
||||
int result = 0;
|
||||
in >> result;
|
||||
if (result == 0)
|
||||
{
|
||||
// 如果登录成功了,获取当前在线人数
|
||||
int n = 0;
|
||||
in >> n;
|
||||
QVector<QString> names;
|
||||
QString name;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
in >> name;
|
||||
names.push_back(name);
|
||||
}
|
||||
this->m_online = names;
|
||||
|
||||
// 初始化数据库
|
||||
IMDAL::instance()->initDatabase(this->m_name);
|
||||
// 获取数据库中有聊天记录的用户名列表
|
||||
QVector<QString> userList = IMDAL::instance()->getUserList();
|
||||
// 将没上线的用户名添加到离线列表中
|
||||
for (int i = 0; i < userList.length(); i++)
|
||||
{
|
||||
// 如果这个名字在在线列表中不存在同时又不是自己
|
||||
if (!this->m_online.contains(userList[i]) && userList[i] != this->m_name)
|
||||
{
|
||||
// 就添加到离线列表中
|
||||
this->m_offline.append(userList[i]);
|
||||
}
|
||||
}
|
||||
// 初始化群聊消息
|
||||
this->m_gruopChatRecord = IMDAL::instance()->getGroupMessage();
|
||||
// 最后发送登录成功消息
|
||||
emit loginResult(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 否则就是登录失败了,发送登录失败的消息
|
||||
emit loginResult(false);
|
||||
}
|
||||
}break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 当连接断开时触发
|
||||
void IMClient::disconnected()
|
||||
{
|
||||
qDebug() << "disconnected";
|
||||
// 发送服务器关闭信号
|
||||
emit serverClose();
|
||||
}
|
||||
|
||||
// 当连接发生错误时触发
|
||||
void IMClient::error(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
qDebug() << socketError;
|
||||
// 发出连接错误信号
|
||||
emit connectError(this->m_socket->errorString());
|
||||
}
|
||||
|
||||
// 向服务器发送数据方法
|
||||
void IMClient::sendData(QString data)
|
||||
{
|
||||
if (this->isOpen())
|
||||
this->m_socket->write(data.toUtf8());
|
||||
}
|
204
IM Porject/IM/imclient.h
Normal file
204
IM Porject/IM/imclient.h
Normal file
@ -0,0 +1,204 @@
|
||||
#ifndef IMCLIENT_H
|
||||
#define IMCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtNetwork>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include "immessage.h"
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* Class IMClient
|
||||
* IM客户端类
|
||||
*
|
||||
* 用于与服务端交互的封装类
|
||||
*
|
||||
* 公开方法有:
|
||||
* login 登录
|
||||
* sendPrivateMessage 发送私聊消息
|
||||
* sendGroupMessage 发送群聊消息
|
||||
*
|
||||
* 发出的信号有:
|
||||
* receivedPrivateMessage 接收到私聊消息信号
|
||||
* receivedGroupMessage 接收到群聊消息信号
|
||||
* userOnline 用户上线信号
|
||||
* userOffline 用户下线信号
|
||||
* serverClose 服务器关闭信号
|
||||
*
|
||||
**********************************/
|
||||
/**
|
||||
* @brief IM客户端类
|
||||
*/
|
||||
class IMClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
// 公开的成员函数
|
||||
protected:
|
||||
explicit IMClient(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief instance 单例对象
|
||||
* @return 单例对象指针
|
||||
*/
|
||||
static IMClient *instance();
|
||||
|
||||
~IMClient();
|
||||
|
||||
/**
|
||||
* @brief connectServer 尝试连接服务器
|
||||
* @param hostName 连接名
|
||||
*/
|
||||
void connectServer(QString hostName);
|
||||
|
||||
/**
|
||||
* @brief login 登录
|
||||
* @param name 用户名
|
||||
*/
|
||||
void login(QString name);
|
||||
|
||||
/**
|
||||
* @brief sendPrivateMessage 发送私聊消息
|
||||
* @param toName 发送给谁
|
||||
* @param content 消息内容
|
||||
*/
|
||||
void sendPrivateMessage(QString toName, QString content);
|
||||
|
||||
/**
|
||||
* @brief sendGroupMessage 发送群聊消息
|
||||
* @param content 消息内容
|
||||
*/
|
||||
void sendGroupMessage(QString content);
|
||||
|
||||
/**
|
||||
* @brief isOpen 连接是否打开
|
||||
* @return
|
||||
*/
|
||||
bool isOpen()
|
||||
{
|
||||
return this->m_socket != nullptr
|
||||
&& this->m_socket->state() != QAbstractSocket::UnconnectedState;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
const QVector<IMMessage> *getChatRecord(QString name);
|
||||
const QVector<IMMessage> *getGroupChatRecord() { return &m_gruopChatRecord; }
|
||||
const QVector<QString> *getOnlineList() { return &m_online; }
|
||||
const QVector<QString> *getOfflineList() { return &m_offline; }
|
||||
QString getName() { return m_name; }
|
||||
|
||||
// 信号
|
||||
signals:
|
||||
/**
|
||||
* @brief loginResult 登录结果
|
||||
* @param isSuccess 是否登录成功
|
||||
*/
|
||||
void loginResult(bool isSuccess);
|
||||
|
||||
/**
|
||||
* @brief receivedPrivateMessage 接收到私聊消息信号
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void receivedPrivateMessage(IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief receivedGroupMessage 接收到群聊消息信号
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void receivedGroupMessage(IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief userOnline 用户上线信号
|
||||
* @param fromName 上线者昵称
|
||||
*/
|
||||
void userOnline(QString fromName);
|
||||
|
||||
/**
|
||||
* @brief userOffline 用户下线信号
|
||||
* @param fromName 下线者昵称
|
||||
*/
|
||||
void userOffline(QString fromName);
|
||||
|
||||
/**
|
||||
* @brief serverConnected 服务器连接成功信号
|
||||
*/
|
||||
void serverConnected();
|
||||
|
||||
/**
|
||||
* @brief serverClose 服务器关闭信号
|
||||
*/
|
||||
void serverClose();
|
||||
|
||||
/**
|
||||
* @brief connectError 连接发生错误信号
|
||||
* @param ErrorInfo 错误信息文本说明
|
||||
*/
|
||||
void connectError(QString ErrorInfo);
|
||||
|
||||
// 槽
|
||||
public slots:
|
||||
/**
|
||||
* @brief connected 连接成功时触发
|
||||
*/
|
||||
void connected();
|
||||
|
||||
/**
|
||||
* @brief readyread 当接收到数据时触发
|
||||
*/
|
||||
void readyread();
|
||||
|
||||
/**
|
||||
* @brief disconnected 当连接断开时触发
|
||||
*/
|
||||
void disconnected();
|
||||
|
||||
/**
|
||||
* @brief error 当连接发生错误时触发
|
||||
* @param socketError 错误信息
|
||||
*/
|
||||
void error(QAbstractSocket::SocketError socketError);
|
||||
|
||||
// 私有成员函数
|
||||
private:
|
||||
/**
|
||||
* @brief sendData 发送数据到服务器
|
||||
* @param data 数据
|
||||
*/
|
||||
void sendData(QString data);
|
||||
|
||||
// 私有的成员变量
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief 当前登录的用户昵称
|
||||
*/
|
||||
QString m_name;
|
||||
|
||||
/**
|
||||
* @brief 客户端的Tcp Socket对象
|
||||
*/
|
||||
QTcpSocket *m_socket;
|
||||
|
||||
/**
|
||||
* @brief 在线人员昵称列表
|
||||
*/
|
||||
QVector<QString> m_online;
|
||||
/**
|
||||
* @brief 离线人员昵称列表
|
||||
*/
|
||||
QVector<QString> m_offline;
|
||||
|
||||
/**
|
||||
* @brief 私聊的聊天记录
|
||||
*/
|
||||
QMap<QString, QVector<IMMessage> > m_chatRecord;
|
||||
|
||||
/**
|
||||
* @brief 群聊的聊天记录
|
||||
*/
|
||||
QVector<IMMessage> m_gruopChatRecord;
|
||||
};
|
||||
|
||||
#endif // IMCLIENT_H
|
241
IM Porject/IM/imdal.cpp
Normal file
241
IM Porject/IM/imdal.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include "imdal.h"
|
||||
#include "immessage.h"
|
||||
|
||||
|
||||
|
||||
IMDAL *IMDAL::instance()
|
||||
{
|
||||
static IMDAL imDAL;
|
||||
return &imDAL;
|
||||
}
|
||||
|
||||
void IMDAL::initDatabase(QString name)
|
||||
{
|
||||
//打印Qt支持的数据库驱动
|
||||
qDebug()<<QSqlDatabase::drivers();
|
||||
|
||||
QSqlDatabase database;
|
||||
// 检测默认连接是否已经存在
|
||||
if (QSqlDatabase::contains(QSqlDatabase::defaultConnection))
|
||||
{
|
||||
// 存在就直接用
|
||||
database = QSqlDatabase::database(QSqlDatabase::defaultConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不存在就添加一个数据库驱动引擎SQLite
|
||||
database = QSqlDatabase::addDatabase("QSQLITE");
|
||||
// 然后打开指定用户的数据库文件
|
||||
database.setDatabaseName(QString("./msgsave_%1.db").arg(name));
|
||||
// database.setUserName("root");
|
||||
// database.setPassword("123456");
|
||||
}
|
||||
|
||||
//打开数据库
|
||||
if(!database.open())
|
||||
{
|
||||
// 如果打开失败 退出程序
|
||||
qDebug()<<database.lastError();
|
||||
qFatal("failed to connect.");
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Open database success!";
|
||||
QStringList tables = database.tables(); //获取数据库中的表
|
||||
qDebug() << QString("表的个数: %1").arg(tables.count()); //打印表的个数
|
||||
// 如果表的数量小于3,说明这是一个新用户登录
|
||||
if (tables.count() < 3)
|
||||
{
|
||||
/*
|
||||
SQL语句:
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR NOT NULL
|
||||
UNIQUE
|
||||
);
|
||||
|
||||
INSERT INTO user (
|
||||
name
|
||||
)
|
||||
VALUES (
|
||||
'xxx'
|
||||
);
|
||||
|
||||
CREATE TABLE message (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
fromID INTEGER NOT NULL
|
||||
REFERENCES user ( id ) ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
time DATETIME NOT NULL
|
||||
DEFAULT ( datetime( 'now', 'localtime' ) ),
|
||||
io CHAR NOT NULL
|
||||
);
|
||||
io这个字段代表是发送还是接受:i收到消息 o发出消息 g群聊消息
|
||||
*/
|
||||
database.transaction();
|
||||
QSqlQuery query;
|
||||
// 创建表并将用户昵称插入表中作为第一条数据存在,id为1
|
||||
query.exec("CREATE TABLE user ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
"name VARCHAR NOT NULL UNIQUE);");
|
||||
query.exec(QString("INSERT INTO user(name) values('%1');").arg(name));
|
||||
query.exec("CREATE TABLE message ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
"fromID INTEGER NOT NULL REFERENCES user(id) ON DELETE CASCADE ON UPDATE CASCADE,"
|
||||
"content TEXT NOT NULL,"
|
||||
"time DATETIME NOT NULL DEFAULT(datetime('now','localtime')),"
|
||||
"io CHAR NOT NULL);");
|
||||
if (!database.commit())
|
||||
qDebug()<<database.lastError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMDAL::addPrivateMessage(QString name, IMMessage msg)
|
||||
{
|
||||
if (!QSqlDatabase::database().isOpen())
|
||||
return;
|
||||
// 获得用户ID
|
||||
int userID = getUserID(name);
|
||||
if (userID == 0)
|
||||
return;
|
||||
// 插入这条私聊消息
|
||||
QSqlQuery query;
|
||||
query.prepare("INSERT INTO message(fromID, content, time, io) "
|
||||
"VALUES(?, ?, ?, ?)");
|
||||
query.addBindValue(userID);
|
||||
query.addBindValue(msg.content);
|
||||
query.addBindValue(msg.time);
|
||||
query.addBindValue(msg.fromName);
|
||||
if (!query.exec())
|
||||
qDebug()<<query.lastError();
|
||||
}
|
||||
|
||||
void IMDAL::addGroupMessage(IMMessage msg)
|
||||
{
|
||||
if (!QSqlDatabase::database().isOpen())
|
||||
return;
|
||||
|
||||
// 获取用户ID
|
||||
int userID = getUserID(msg.fromName);
|
||||
if (userID == 0)
|
||||
return;
|
||||
// 插入这条群聊消息
|
||||
QSqlQuery query;
|
||||
query.prepare("INSERT INTO message(fromID, content, time, io) "
|
||||
"VALUES(?, ?, ?, 'g')");
|
||||
query.addBindValue(userID);
|
||||
query.addBindValue(msg.content);
|
||||
query.addBindValue(msg.time);
|
||||
if (!query.exec())
|
||||
qDebug()<<query.lastError();
|
||||
}
|
||||
|
||||
QVector<IMMessage> IMDAL::getPrivateMessage(QString name)
|
||||
{
|
||||
QVector<IMMessage> msgList;
|
||||
int userID = 0;
|
||||
if (!QSqlDatabase::database().isOpen())
|
||||
return msgList;
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT id FROM user WHERE name = ?");
|
||||
query.addBindValue(name);
|
||||
if(!query.exec())
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
return msgList;
|
||||
}
|
||||
// 获取这个昵称的id
|
||||
while(query.next())
|
||||
userID = query.value(0).toInt();
|
||||
// 如果没有这个人的记录,直接返回空
|
||||
if (userID == 0)
|
||||
return msgList;
|
||||
|
||||
// 否则查找这个用户的消息
|
||||
query.prepare("SELECT io, content, time FROM message WHERE fromID = ? AND io != 'g'");
|
||||
query.addBindValue(userID);
|
||||
if(!query.exec())
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
return msgList;
|
||||
}
|
||||
// 将所有消息添加到列表中
|
||||
while(query.next())
|
||||
msgList.append(IMMessage(query.value(0).toString(), query.value(1).toString(), query.value(2).toDateTime()));
|
||||
|
||||
return msgList;
|
||||
}
|
||||
|
||||
QVector<IMMessage> IMDAL::getGroupMessage()
|
||||
{
|
||||
QVector<IMMessage> msgList;
|
||||
if (!QSqlDatabase::database().isOpen())
|
||||
return msgList;
|
||||
QSqlQuery query;
|
||||
if(!query.exec("SELECT name, content, time FROM message,user WHERE io == 'g' AND user.id = fromID"))
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
return msgList;
|
||||
}
|
||||
// 将所有消息添加到列表中
|
||||
while(query.next())
|
||||
msgList.append(IMMessage(query.value(0).toString(), query.value(1).toString(), query.value(2).toDateTime()));
|
||||
|
||||
return msgList;
|
||||
}
|
||||
|
||||
QVector<QString> IMDAL::getUserList()
|
||||
{
|
||||
qDebug() << "getUserList()";
|
||||
QVector<QString> names;
|
||||
if (!QSqlDatabase::database().isOpen())
|
||||
return names;
|
||||
QSqlQuery query;
|
||||
if (!query.exec("SELECT name FROM user"))
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (query.next())
|
||||
names.append(query.value(0).toString());
|
||||
}
|
||||
qDebug() << names;
|
||||
return names;
|
||||
}
|
||||
|
||||
int IMDAL::getUserID(QString name)
|
||||
{
|
||||
QSqlQuery query;
|
||||
int userID = 0;
|
||||
query.prepare("SELECT id FROM user WHERE name = ?");
|
||||
query.addBindValue(name);
|
||||
if(!query.exec())
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
return 0;
|
||||
}
|
||||
// 获取这个昵称的id
|
||||
while(query.next())
|
||||
userID = query.value(0).toInt();
|
||||
if (userID)
|
||||
return userID;
|
||||
|
||||
// 如果没有这个人的记录,那么就创建这个人的ID
|
||||
query.prepare("INSERT INTO user(name) VALUES(?)");
|
||||
query.addBindValue(name);
|
||||
if(!query.exec())
|
||||
{
|
||||
qDebug()<<query.lastError();
|
||||
return 0;
|
||||
}
|
||||
return query.lastInsertId().toInt();
|
||||
}
|
59
IM Porject/IM/imdal.h
Normal file
59
IM Porject/IM/imdal.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef IMDAL_H
|
||||
#define IMDAL_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include "immessage.h"
|
||||
|
||||
// IM数据层
|
||||
class IMDAL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief instance 单例对象
|
||||
* @return 单例对象指针
|
||||
*/
|
||||
static IMDAL *instance();
|
||||
|
||||
/**
|
||||
* @brief initDatabase 初始化数据库
|
||||
* @param name 用户名
|
||||
*/
|
||||
void initDatabase(QString name);
|
||||
|
||||
/**
|
||||
* @brief addPrivateMessage 添加一条私聊消息
|
||||
* @param name 用户名
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void addPrivateMessage(QString name, IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief addGroupMessage 添加一条群聊消息
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void addGroupMessage(IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief getPrivateMessage 获取私聊消息
|
||||
* @param name 对方昵称
|
||||
* @return 消息内容
|
||||
*/
|
||||
QVector<IMMessage> getPrivateMessage(QString name);
|
||||
|
||||
/**
|
||||
* @brief getGroupMessage 获取群聊消息
|
||||
* @return 消息内容
|
||||
*/
|
||||
QVector<IMMessage> getGroupMessage();
|
||||
|
||||
/**
|
||||
* @brief getUserList 获取用户列表
|
||||
* @return 用户列表
|
||||
*/
|
||||
QVector<QString> getUserList();
|
||||
private:
|
||||
int getUserID(QString name);
|
||||
};
|
||||
|
||||
#endif // IMDAL_H
|
33
IM Porject/IM/immessage.h
Normal file
33
IM Porject/IM/immessage.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef IMMESSAGE_H
|
||||
#define IMMESSAGE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
|
||||
struct IMMessage
|
||||
{
|
||||
IMMessage(){}
|
||||
|
||||
IMMessage(QString fromName, QString content, QDateTime time)
|
||||
: fromName(fromName),
|
||||
content(content),
|
||||
time(time) {}
|
||||
|
||||
|
||||
/**
|
||||
* @brief fromName 发送者
|
||||
*/
|
||||
QString fromName;
|
||||
|
||||
/**
|
||||
* @brief content 内容
|
||||
*/
|
||||
QString content;
|
||||
|
||||
/**
|
||||
* @brief time 时间
|
||||
*/
|
||||
QDateTime time;
|
||||
};
|
||||
|
||||
#endif // IMMESSAGE_H
|
14
IM Porject/IM/main.cpp
Normal file
14
IM Porject/IM/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "formlogin.h"
|
||||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
QTextCodec::setCodecForLocale(codec);
|
||||
// 启动登录窗口
|
||||
FormLogin l;
|
||||
l.show();
|
||||
return a.exec();
|
||||
}
|
190
IM Porject/IM/mainwindow.cpp
Normal file
190
IM Porject/IM/mainwindow.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include <QMessageBox>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(IMClient::instance(), &IMClient::receivedPrivateMessage, this, &MainWindow::receivedPrivateMessage);
|
||||
connect(IMClient::instance(), &IMClient::receivedGroupMessage, this, &MainWindow::receivedGroupMessage);
|
||||
connect(IMClient::instance(), &IMClient::userOnline, this, &MainWindow::userOnline);
|
||||
connect(IMClient::instance(), &IMClient::userOffline, this, &MainWindow::userOffline);
|
||||
connect(IMClient::instance(), &IMClient::serverClose, this, &MainWindow::serverClose);
|
||||
// 初始化好友列表
|
||||
ui->listWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
updateUserList();
|
||||
|
||||
// 设置窗口标题
|
||||
this->setWindowTitle("IM:" + IMClient::instance()->getName());
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// 当发送按钮被点击时
|
||||
void MainWindow::on_btnSend_clicked()
|
||||
{
|
||||
// 获取输入框的内容
|
||||
QString text = ui->plainTextEdit->toPlainText();
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
// 如果要发送的文本大于255,提示超出范围并返回
|
||||
if (text.length() > 255)
|
||||
{
|
||||
QMessageBox::warning(this, "警告", "您输入的文本太长");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果当前没有选中任何人,提示并返回
|
||||
if (ui->listWidget->currentItem() == nullptr)
|
||||
{
|
||||
QMessageBox::information(this, "提示", "请选择对话对象!");
|
||||
return;
|
||||
}
|
||||
// 验证通过后清空输入框
|
||||
ui->plainTextEdit->clear();
|
||||
|
||||
// 用自己的名字组装消息结构
|
||||
IMMessage msg(IMClient::instance()->getName(), text, QDateTime::currentDateTime());
|
||||
// 添加到对话框中
|
||||
this->addMessage(msg);
|
||||
// 如果当前选中的是群聊,发送群聊消息,否则发送私聊消息
|
||||
if (ui->listWidget->currentItem() == this->pGruopItem)
|
||||
IMClient::instance()->sendGroupMessage(text);
|
||||
else
|
||||
IMClient::instance()->sendPrivateMessage(ui->listWidget->currentItem()->text(), text);
|
||||
}
|
||||
|
||||
// 接收到私聊消息时
|
||||
void MainWindow::receivedPrivateMessage(IMMessage msg)
|
||||
{
|
||||
// 如果当前没有选中发消息这个人,直接返回(优化的话就是新消息提醒)
|
||||
if (ui->listWidget->currentItem() == nullptr)
|
||||
return;
|
||||
if (ui->listWidget->currentItem() == this->pGruopItem)
|
||||
return;
|
||||
if (ui->listWidget->currentItem()->text() != msg.fromName)
|
||||
return;
|
||||
|
||||
// 将消息添加到对话框中
|
||||
this->addMessage(msg);
|
||||
}
|
||||
|
||||
void MainWindow::receivedGroupMessage(IMMessage msg)
|
||||
{
|
||||
if (ui->listWidget->currentItem() == this->pGruopItem)
|
||||
this->addMessage(msg);
|
||||
}
|
||||
|
||||
void MainWindow::userOnline(QString fromName)
|
||||
{
|
||||
updateUserList();
|
||||
QMessageBox::information(nullptr, "提示", fromName + " 已上线");
|
||||
}
|
||||
|
||||
void MainWindow::userOffline(QString fromName)
|
||||
{
|
||||
updateUserList();
|
||||
QMessageBox::information(nullptr, "提示", fromName + " 已下线");
|
||||
}
|
||||
|
||||
void MainWindow::serverClose()
|
||||
{
|
||||
QMessageBox::warning(this, "警告", "服务器已经关闭,程序即将退出!");
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
// 更新用户列表
|
||||
void MainWindow::updateUserList()
|
||||
{
|
||||
ui->listWidget->setCurrentItem(nullptr);
|
||||
int n = ui->listWidget->count();
|
||||
// 清空表,重新加载
|
||||
for (int i = 0; i < n; i++)
|
||||
delete ui->listWidget->takeItem(0);
|
||||
|
||||
// 添加群聊项在表中
|
||||
pGruopItem = new QListWidgetItem(QIcon(":icons/images/group.png"), "群聊");
|
||||
ui->listWidget->addItem(pGruopItem);
|
||||
|
||||
// 添加在线人员在表中
|
||||
const QVector<QString> *pUserList = IMClient::instance()->getOnlineList();
|
||||
for (int i = 0; i < pUserList->length(); i++)
|
||||
ui->listWidget->addItem(new QListWidgetItem(QIcon(":icons/images/userOnline.png"), pUserList->at(i)));
|
||||
|
||||
// 添加离线人员到表中
|
||||
pUserList = IMClient::instance()->getOfflineList();
|
||||
for (int i = 0; i < pUserList->length(); i++)
|
||||
ui->listWidget->addItem(new QListWidgetItem(QIcon(":icons/images/userOffline.png"), pUserList->at(i)));
|
||||
}
|
||||
|
||||
void MainWindow::setChatRecord(const QVector<IMMessage> *chatRecord, const QString *name)
|
||||
{
|
||||
// 清空聊天框
|
||||
ui->textBrowser->clear();
|
||||
// 如果是空的直接返回
|
||||
if (chatRecord == nullptr)
|
||||
return;
|
||||
// 如果name为空表示是群聊消息
|
||||
if (name == nullptr)
|
||||
{
|
||||
// 群聊消息直接添加即可
|
||||
for (int i = 0; i < chatRecord->length(); ++i)
|
||||
this->addMessage(chatRecord->at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 私聊消息需要经过转换,因为私聊消息的fromName使用i和o来代表接收或者发出
|
||||
for (int i = 0; i < chatRecord->length(); ++i)
|
||||
{
|
||||
IMMessage msg = chatRecord->at(i);
|
||||
// 如果是i表示接收的消息,用传进来的名字代替,否则是接收的消息,用自己的名字来代替
|
||||
msg.fromName = msg.fromName == "i" ? *name : IMClient::instance()->getName();
|
||||
this->addMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addMessage(const IMMessage &msg)
|
||||
{
|
||||
QString timeStr;
|
||||
// 选择时间的格式 如果是同一天,那么时间就按 12:00:00 这种格式显示
|
||||
if (msg.time.date() > QDateTime::currentDateTime().date().addDays(-1))
|
||||
timeStr = msg.time.toString("HH:mm:ss");
|
||||
// 否则如果超过一天,但是小于一年,则显示月份日期 12/10 12:00:00
|
||||
else if (msg.time.date() > QDateTime::currentDateTime().date().addYears(-1))
|
||||
timeStr = msg.time.toString("MM/dd HH:mm:ss");
|
||||
// 否则显示年份
|
||||
else
|
||||
timeStr = msg.time.toString("yyyy/MM.dd HH:mm:ss");
|
||||
|
||||
// 显示文本
|
||||
ui->textBrowser->append(QString("<font color=\"%1\">%2 %3</font>").arg(msg.fromName == IMClient::instance()->getName() ? "#008040" : "#0000ff").arg(msg.fromName).arg(timeStr));
|
||||
ui->textBrowser->insertPlainText(QString("\n %1\n").arg(msg.content));
|
||||
ui->textBrowser->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void MainWindow::on_listWidget_itemClicked(QListWidgetItem *item)
|
||||
{
|
||||
// 如果选中项为空,那就清空对话框
|
||||
if (item == nullptr)
|
||||
this->setChatRecord(nullptr);
|
||||
|
||||
// 如果选中了群聊选项,加载群聊的聊天记录
|
||||
if (item == this->pGruopItem)
|
||||
this->setChatRecord(IMClient::instance()->getGroupChatRecord());
|
||||
else
|
||||
{
|
||||
// 否则就是选中了用户,读取这个用户的聊天记录
|
||||
QString name = item->text();
|
||||
this->setChatRecord(IMClient::instance()->getChatRecord(name), &name);
|
||||
}
|
||||
}
|
83
IM Porject/IM/mainwindow.h
Normal file
83
IM Porject/IM/mainwindow.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QListWidgetItem>
|
||||
#include <QVector>
|
||||
#include "imclient.h"
|
||||
#include "immessage.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void on_btnSend_clicked();
|
||||
|
||||
void on_listWidget_itemClicked(QListWidgetItem *item);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief receivedPrivateMessage 接收到私聊消息时触发
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void receivedPrivateMessage(IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief receivedGroupMessage 接收到群聊消息时触发
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void receivedGroupMessage(IMMessage msg);
|
||||
|
||||
/**
|
||||
* @brief userOnline 用户上线时触发
|
||||
* @param fromName 上线者昵称
|
||||
*/
|
||||
void userOnline(QString fromName);
|
||||
|
||||
/**
|
||||
* @brief userOffline 用户下线时触发
|
||||
* @param fromName 下线者昵称
|
||||
*/
|
||||
void userOffline(QString fromName);
|
||||
|
||||
/**
|
||||
* @brief serverClose 服务器关闭时触发
|
||||
*/
|
||||
void serverClose();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief updateUserList 更新用户列表
|
||||
*/
|
||||
void updateUserList();
|
||||
|
||||
/**
|
||||
* @brief setChatRecord 设置当前聊天记录
|
||||
* @param chatRecord 聊天记录内容
|
||||
*/
|
||||
void setChatRecord(const QVector<IMMessage> *chatRecord, const QString *name = nullptr);
|
||||
|
||||
/**
|
||||
* @brief addMessage 添加一条消息
|
||||
* @param msg 消息内容
|
||||
*/
|
||||
void addMessage(const IMMessage &msg);
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
/**
|
||||
* @brief pGruopItem 群聊项指针
|
||||
*/
|
||||
QListWidgetItem *pGruopItem;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
149
IM Porject/IM/mainwindow.ui
Normal file
149
IM Porject/IM/mainwindow.ui
Normal file
@ -0,0 +1,149 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<widget class="QTextBrowser" name="textBrowser">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<y>7</y>
|
||||
<width>561</width>
|
||||
<height>371</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="cursor" stdset="0">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<y>400</y>
|
||||
<width>561</width>
|
||||
<height>71</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="cursor" stdset="0">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnSend">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>720</x>
|
||||
<y>470</y>
|
||||
<width>75</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>390</y>
|
||||
<width>571</width>
|
||||
<height>111</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>230</x>
|
||||
<y>0</y>
|
||||
<width>571</width>
|
||||
<height>388</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>229</width>
|
||||
<height>501</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255)</string>
|
||||
</property>
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>218</width>
|
||||
<height>481</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<zorder>widget_3</zorder>
|
||||
<zorder>widget_2</zorder>
|
||||
<zorder>widget</zorder>
|
||||
<zorder>textBrowser</zorder>
|
||||
<zorder>plainTextEdit</zorder>
|
||||
<zorder>btnSend</zorder>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
59
IM Porject/IM/protocol.h
Normal file
59
IM Porject/IM/protocol.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
/************************************************
|
||||
* IM通讯协议规定
|
||||
*
|
||||
* 功能码 [参数]
|
||||
*
|
||||
* 客户端功能码规定: 参数: 例子: 说明:
|
||||
* 1 = 请求登录 用户昵称 1 张三 当客户端登录时必须先发送这条命令,告诉服务端自己的昵称
|
||||
* 2 = 发送私聊消息 私聊对象 消息内容 2 李四 你妈喊你回家吃饭 当A向B发送一条私聊消息时,A要向服务器发送这条指令,告诉服务器消息发给谁和发什么消息
|
||||
* 3 = 发送群聊消息 消息内容 3 大家好,我是张三 当A向群聊发送一条消息时,直接告诉服务端需要发什么内容即可
|
||||
*
|
||||
* 服务端功能码规定: 参数: 例子: 说明:
|
||||
* 1 = 发送私聊消息 用户昵称 消息内容 1 张三 你妈喊你回家吃饭 当A向B发送一条私聊消息时,B会收到这条指令,其中昵称是指A(发送者)的昵称
|
||||
* 2 = 发送群聊消息 用户昵称 消息内容 2 张三 大家好,我是张三 当A向群聊发送一条消息时,所有人都会收到这条指令,其中昵称是指A(发送者)的昵称
|
||||
* 3 = 某人上线 用户昵称 3 张三 当A上线时,所有人都会收到这条指令,其中昵称是A(上线者)的昵称
|
||||
* 4 = 某人下线 用户昵称 4 张三 当A下线时,所有人都会手套这条指令,其中昵称是A(下线者)的昵称
|
||||
* 10 = 登录结果 是否成功(0:成功,!0:失败) [当前在线人数] [当前在线人员列表]
|
||||
* 成功时 10 0 4 张三 李四 王五 赵六 当客户端发送登录请求后,如果登录成功则返回当前在线人数与昵称列表,如果失败就返回一个!0值
|
||||
* 失败时 10 1
|
||||
*
|
||||
***********************************************/
|
||||
|
||||
/**
|
||||
* @brief 服务端功能码
|
||||
*/
|
||||
enum ServerFunctionCode {
|
||||
// 私聊消息
|
||||
PrivateMessage = 1,
|
||||
|
||||
// 群聊消息
|
||||
GroupMessage = 2,
|
||||
|
||||
// 用户上线
|
||||
UserOnline = 3,
|
||||
|
||||
// 用户下线
|
||||
UserOffline = 4,
|
||||
|
||||
// 登录结果
|
||||
LoginResult = 10
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 客户端功能码
|
||||
*/
|
||||
enum ClientFunctionCode {
|
||||
// 登录
|
||||
Login = 1,
|
||||
|
||||
// 发送私聊消息
|
||||
SendPrivateMessage = 2,
|
||||
|
||||
// 发送群聊消息
|
||||
SendGroupMessage = 3
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_H
|
7
IM Porject/IM/resources.qrc
Normal file
7
IM Porject/IM/resources.qrc
Normal file
@ -0,0 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>images/group.png</file>
|
||||
<file>images/userOffline.png</file>
|
||||
<file>images/userOnline.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
29
IM Porject/IMService/IMService.pro
Normal file
29
IM Porject/IMService/IMService.pro
Normal file
@ -0,0 +1,29 @@
|
||||
QT -= gui
|
||||
QT += network
|
||||
|
||||
CONFIG += c++11 console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
imservice.cpp
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
HEADERS += \
|
||||
imservice.h \
|
||||
protocol.h
|
322
IM Porject/IMService/IMService.pro.user
Normal file
322
IM Porject/IMService/IMService.pro.user
Normal file
@ -0,0 +1,322 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.7.2, 2018-12-08T20:06:10. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{2d03fc4c-541a-4fa5-8f5c-ae92a1998dce}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
|
||||
<value type="QString">-fno-delayed-template-parsing</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.11.2 MinGW 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.11.2 MinGW 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5112.win32_mingw53_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IMService-Desktop_Qt_5_11_2_MinGW_32bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IMService-Desktop_Qt_5_11_2_MinGW_32bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">E:/C++/Qt/build-IMService-Desktop_Qt_5_11_2_MinGW_32bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">IMService</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:E:/C++/Qt/IMService/IMService.pro</value>
|
||||
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">IMService.pro</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">E:/C++/Qt/build-IMService-Desktop_Qt_5_11_2_MinGW_32bit-Debug</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
229
IM Porject/IMService/imservice.cpp
Normal file
229
IM Porject/IMService/imservice.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
#include "imservice.h"
|
||||
#include "protocol.h"
|
||||
#include <QDebug>
|
||||
|
||||
// 构造函数
|
||||
IMService::IMService(QObject *parent)
|
||||
: QObject(parent),
|
||||
m_server(new QTcpServer),
|
||||
m_clientSocket(new QMap<QString, QTcpSocket *>),
|
||||
m_clientNames(new QMap<QTcpSocket *, QString>)
|
||||
{
|
||||
connect(this->m_server, &QTcpServer::newConnection, this, &IMService::newConnection);
|
||||
if (this->m_server->listen(QHostAddress::Any, 9876))
|
||||
qDebug() << "Service open SUCCESS!";
|
||||
else
|
||||
qDebug() << this->m_server->errorString(); //错误信息
|
||||
|
||||
}
|
||||
|
||||
IMService::~IMService()
|
||||
{
|
||||
m_server->close();
|
||||
delete m_server;
|
||||
delete m_clientSocket;
|
||||
delete m_clientNames;
|
||||
qDebug() << "Service Close!";
|
||||
}
|
||||
|
||||
void IMService::closeService()
|
||||
{
|
||||
// 遍历并关闭所有Socket连接
|
||||
for (auto it : *(this->m_clientSocket))
|
||||
it->close();
|
||||
// 清空表
|
||||
this->m_clientSocket->clear();
|
||||
this->m_clientNames->clear();
|
||||
}
|
||||
|
||||
// 当有新连接进入时
|
||||
void IMService::newConnection()
|
||||
{
|
||||
// 获取这个连接的Socket
|
||||
QTcpSocket *socketTemp = this->m_server->nextPendingConnection();
|
||||
|
||||
// 当接收到数据时触发readyRead
|
||||
connect(socketTemp, &QTcpSocket::readyRead, this, &IMService::readyRead);
|
||||
|
||||
// 当连接断开时触发disconnected
|
||||
connect(socketTemp, &QTcpSocket::disconnected, this, &IMService::disconnected);
|
||||
|
||||
qDebug() << "newConnection!";
|
||||
}
|
||||
|
||||
// 当连接断开时触发
|
||||
void IMService::disconnected()
|
||||
{
|
||||
qDebug() << "disconnected!";
|
||||
|
||||
// 获取断开连接的对象
|
||||
QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
|
||||
// 释放内存
|
||||
sender->deleteLater();
|
||||
|
||||
// 先查一下这个连接是否存在表中,如果没在,说明这个连接没上线,直接return即可
|
||||
if (!this->m_clientNames->contains(sender))
|
||||
return;
|
||||
|
||||
// 否则说明这是一个在线用户断开连接
|
||||
// 记录这个用户的昵称
|
||||
QString senderName = this->m_clientNames->value(sender);
|
||||
|
||||
// 将这个用户从表中移除
|
||||
this->m_clientSocket->remove(senderName);
|
||||
this->m_clientNames->remove(sender);
|
||||
|
||||
// 通知其他人该用户离线
|
||||
this->userOffline(senderName);
|
||||
}
|
||||
|
||||
// 当接收到数据时触发
|
||||
void IMService::readyRead()
|
||||
{
|
||||
// 获取接收到数据的对象
|
||||
QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
|
||||
// 获取数据
|
||||
QByteArray data = sender->readAll();
|
||||
QTextStream in(data, QIODevice::ReadOnly);
|
||||
qDebug() << "readyread:" << data;
|
||||
|
||||
|
||||
// 进行协议分析与任务调度
|
||||
int functionID = 0;
|
||||
in >> functionID;
|
||||
|
||||
// 如果是登录的功能码
|
||||
if (functionID == ClientFunctionCode::Login)
|
||||
{
|
||||
QString name;
|
||||
in >> name;
|
||||
// 执行登录
|
||||
this->userLogin(name, sender);
|
||||
}
|
||||
// 检测这个连接有没有登录
|
||||
else if (this->m_clientNames->contains(sender))
|
||||
{
|
||||
// 如果是私聊消息
|
||||
if (functionID == ClientFunctionCode::SendPrivateMessage)
|
||||
{
|
||||
// 获取要发送的用户昵称
|
||||
QString toName;
|
||||
in >> toName;
|
||||
in.seek(in.pos() + 1);
|
||||
|
||||
// 将剩下的内容全部发送
|
||||
this->sendPrivateMessage(this->m_clientNames->value(sender), toName, in.readAll());
|
||||
}
|
||||
// 否则如果是群聊消息
|
||||
else if (functionID == ClientFunctionCode::SendGroupMessage)
|
||||
{
|
||||
in.seek(in.pos() + 1);
|
||||
this->sendGroupMessage(this->m_clientNames->value(sender), in.readAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMService::sendData(QTcpSocket *socket, QString data)
|
||||
{
|
||||
if (socket != nullptr && socket->isOpen())
|
||||
socket->write(data.toUtf8());
|
||||
}
|
||||
|
||||
/*
|
||||
enum ServerFunctionCode {
|
||||
// 私聊消息
|
||||
PrivateMessage = 1,
|
||||
|
||||
// 群聊消息
|
||||
GroupMessage = 2,
|
||||
|
||||
// 用户上线
|
||||
UserOnline = 3,
|
||||
|
||||
// 用户下线
|
||||
UserOffline = 4,
|
||||
|
||||
// 登录结果
|
||||
LoginResult = 10
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
// 用户登录
|
||||
// 参数:name 用户昵称
|
||||
void IMService::userLogin(QString name, QTcpSocket *socket)
|
||||
{
|
||||
qDebug() << "userLogin(): user name:" << name << "\tsocket:" << socket;
|
||||
// 如果这个昵称或者连接已经登录了
|
||||
if (this->m_clientSocket->contains(name) || this->m_clientNames->contains(socket))
|
||||
{
|
||||
qDebug() << "Login failed!";
|
||||
// 发送登录结果:登录失败
|
||||
this->sendData(this->m_clientSocket->value(name), QString("%1 1").arg(ServerFunctionCode::LoginResult));
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Login success!";
|
||||
// 获取当前在线的用户昵称
|
||||
QList<QString> temp = this->m_clientSocket->keys();
|
||||
this->m_clientSocket->insert(name, socket);
|
||||
this->m_clientNames->insert(socket, name);
|
||||
// 将所有在线用户的昵称组合
|
||||
QString ret = QString("%1 0 %2").arg(ServerFunctionCode::LoginResult).arg(temp.length());
|
||||
QTextStream ts(&ret);
|
||||
for (QString it : temp)
|
||||
ts << ' ' << it;
|
||||
qDebug() << "ret:" << ret;
|
||||
// 发送登录结果:登录成功! 并返回当前在线人员数据
|
||||
this->sendData(this->m_clientSocket->value(name), ret);
|
||||
|
||||
// 通知其他人改用户上线
|
||||
this->userOnline(name);
|
||||
}
|
||||
}
|
||||
|
||||
// 发送私聊消息
|
||||
// 参数:fromName 发送者昵称
|
||||
// 参数:toName 接收者昵称
|
||||
// 参数:content 内容
|
||||
void IMService::sendPrivateMessage(QString fromName, QString toName, QString content)
|
||||
{
|
||||
qDebug() << "sendPrivateMessage(): fromName:" << fromName << "\ttoName" << toName << "\tcontent" << content;
|
||||
// 如果该用户存在才发送
|
||||
if (this->m_clientSocket->contains(toName))
|
||||
this->sendData(this->m_clientSocket->value(toName), QString("%1 %2 %3").arg(ServerFunctionCode::PrivateMessage).arg(fromName).arg(content));
|
||||
}
|
||||
|
||||
// 发送群聊消息
|
||||
// 参数:fromName 发送者昵称
|
||||
// 参数:content 内容
|
||||
void IMService::sendGroupMessage(QString fromName, QString content)
|
||||
{
|
||||
qDebug() << "sendGroupMessage(): fromName:" << fromName << "\tcontent" << content;
|
||||
QString data = QString("%1 %2 %3").arg(ServerFunctionCode::GroupMessage).arg(fromName).arg(content);
|
||||
for (auto it = this->m_clientSocket->begin(); it != this->m_clientSocket->end(); it++)
|
||||
if (it.key() != fromName)
|
||||
this->sendData(it.value(), data);
|
||||
}
|
||||
|
||||
// 用户上线
|
||||
// 参数:name 用户昵称
|
||||
void IMService::userOnline(QString name)
|
||||
{
|
||||
qDebug() << "userOnline(): name:" << name;
|
||||
QString data = QString("%1 %2").arg(ServerFunctionCode::UserOnline).arg(name);
|
||||
for (auto it = this->m_clientSocket->begin(); it != this->m_clientSocket->end(); it++)
|
||||
if (it.key() != name)
|
||||
this->sendData(it.value(), data);
|
||||
}
|
||||
|
||||
// 用户离线
|
||||
// 参数:name 用户昵称
|
||||
void IMService::userOffline(QString name)
|
||||
{
|
||||
qDebug() << "userOffline(): name:" << name;
|
||||
QString data = QString("%1 %2").arg(ServerFunctionCode::UserOffline).arg(name);
|
||||
for (auto it = this->m_clientSocket->begin(); it != this->m_clientSocket->end(); it++)
|
||||
if (it.key() != name)
|
||||
this->sendData(it.value(), data);
|
||||
}
|
129
IM Porject/IMService/imservice.h
Normal file
129
IM Porject/IMService/imservice.h
Normal file
@ -0,0 +1,129 @@
|
||||
#ifndef IMSERVICE_H
|
||||
#define IMSERVICE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtNetwork>
|
||||
#include <QMap>
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* Class IMService
|
||||
* IM服务端类
|
||||
*
|
||||
* 用于与客户端交互的封装类
|
||||
*
|
||||
* 公开方法有:
|
||||
* login 登录
|
||||
* sendPrivateMessage 发送私聊消息
|
||||
* sendGroupMessage 发送群聊消息
|
||||
*
|
||||
* 发出的信号有:
|
||||
* receivedPrivateMessage 接收到私聊消息信号
|
||||
* receivedGroupMessage 接收到群聊消息信号
|
||||
* userOnline 用户上线信号
|
||||
* userOffline 用户下线信号
|
||||
* serverClose 服务器关闭信号
|
||||
*
|
||||
**********************************/
|
||||
|
||||
class IMService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// 公开成员函数
|
||||
public:
|
||||
explicit IMService(QObject *parent = nullptr);
|
||||
|
||||
~IMService();
|
||||
|
||||
/**
|
||||
* @brief closeService 关闭服务 断开所有Socket连接
|
||||
*/
|
||||
void closeService();
|
||||
// 信号
|
||||
signals:
|
||||
|
||||
|
||||
// 槽
|
||||
public slots:
|
||||
/**
|
||||
* @brief newConnection 当有新连接进入时
|
||||
*/
|
||||
void newConnection();
|
||||
|
||||
/**
|
||||
* @brief disconnected 当连接断开时触发
|
||||
*/
|
||||
void disconnected();
|
||||
|
||||
/**
|
||||
* @brief readyRead 当接收到数据时触发
|
||||
*/
|
||||
void readyRead();
|
||||
|
||||
// 私有成员函数
|
||||
private:
|
||||
// 发送数据到socket对象中
|
||||
/**
|
||||
* @brief sendData 发送数据到socket对象中
|
||||
* @param socket 指定socket对象
|
||||
* @param data 要发送的数据
|
||||
*/
|
||||
void sendData(QTcpSocket *socket, QString data);
|
||||
|
||||
/**
|
||||
* @brief userLogin 用户登录
|
||||
* @param name 用户昵称
|
||||
* @param socket socket对象
|
||||
*/
|
||||
void userLogin(QString name, QTcpSocket *socket);
|
||||
|
||||
/**
|
||||
* @brief sendPrivateMessage 发送私聊消息
|
||||
* @param fromName 发送者昵称
|
||||
* @param toName 接收者昵称
|
||||
* @param content 内容
|
||||
*/
|
||||
void sendPrivateMessage(QString fromName, QString toName, QString content);
|
||||
|
||||
/**
|
||||
* @brief sendGroupMessage 发送群聊消息
|
||||
* @param fromName 发送者昵称
|
||||
* @param content 内容
|
||||
*/
|
||||
void sendGroupMessage(QString fromName, QString content);
|
||||
|
||||
/**
|
||||
* @brief userOnline 用户上线
|
||||
* @param name 用户昵称
|
||||
*/
|
||||
void userOnline(QString name);
|
||||
|
||||
/**
|
||||
* @brief userOffline 用户离线
|
||||
* @param name 用户昵称
|
||||
*/
|
||||
void userOffline(QString name);
|
||||
|
||||
// 私有成员变量
|
||||
private:
|
||||
/**
|
||||
* @brief m_server 服务端的Tcp Server对象
|
||||
*/
|
||||
QTcpServer *m_server;
|
||||
|
||||
// 客户端的Tcp Socket连接列表
|
||||
// QMap是一个键值对容器,在这里key是用户的昵称,value是用户的Socket连接对象
|
||||
// 每当一个新用户上线,将会添加到该容器中
|
||||
// 当用户下线时则从容器中删除
|
||||
/**
|
||||
* @brief m_clientSocket 客户端的Tcp Socket连接列表
|
||||
*/
|
||||
QMap<QString, QTcpSocket *> *m_clientSocket;
|
||||
/**
|
||||
* @brief m_clientNames 客户端的昵称列表
|
||||
*/
|
||||
QMap<QTcpSocket *, QString> *m_clientNames;
|
||||
};
|
||||
|
||||
#endif // IMSERVICE_H
|
13
IM Porject/IMService/main.cpp
Normal file
13
IM Porject/IMService/main.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QTextCodec>
|
||||
#include "imservice.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
QTextCodec::setCodecForLocale(codec);
|
||||
static IMService imService;
|
||||
return a.exec();
|
||||
}
|
59
IM Porject/IMService/protocol.h
Normal file
59
IM Porject/IMService/protocol.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
/************************************************
|
||||
* IM通讯协议规定
|
||||
*
|
||||
* 功能码 [参数]
|
||||
*
|
||||
* 客户端功能码规定: 参数: 例子: 说明:
|
||||
* 1 = 请求登录 用户昵称 1 张三 当客户端登录时必须先发送这条命令,告诉服务端自己的昵称
|
||||
* 2 = 发送私聊消息 私聊对象 消息内容 2 李四 你妈喊你回家吃饭 当A向B发送一条私聊消息时,A要向服务器发送这条指令,告诉服务器消息发给谁和发什么消息
|
||||
* 3 = 发送群聊消息 消息内容 3 大家好,我是张三 当A向群聊发送一条消息时,直接告诉服务端需要发什么内容即可
|
||||
*
|
||||
* 服务端功能码规定: 参数: 例子: 说明:
|
||||
* 1 = 发送私聊消息 用户昵称 消息内容 1 张三 你妈喊你回家吃饭 当A向B发送一条私聊消息时,B会收到这条指令,其中昵称是指A(发送者)的昵称
|
||||
* 2 = 发送群聊消息 用户昵称 消息内容 2 张三 大家好,我是张三 当A向群聊发送一条消息时,所有人都会收到这条指令,其中昵称是指A(发送者)的昵称
|
||||
* 3 = 某人上线 用户昵称 3 张三 当A上线时,所有人都会收到这条指令,其中昵称是A(上线者)的昵称
|
||||
* 4 = 某人下线 用户昵称 4 张三 当A下线时,所有人都会手套这条指令,其中昵称是A(下线者)的昵称
|
||||
* 10 = 登录结果 是否成功(0:成功,!0:失败) [当前在线人数] [当前在线人员列表]
|
||||
* 成功时 10 0 4 张三 李四 王五 赵六 当客户端发送登录请求后,如果登录成功则返回当前在线人数与昵称列表,如果失败就返回一个!0值
|
||||
* 失败时 10 1
|
||||
*
|
||||
***********************************************/
|
||||
|
||||
/**
|
||||
* @brief 服务端功能码
|
||||
*/
|
||||
enum ServerFunctionCode {
|
||||
// 私聊消息
|
||||
PrivateMessage = 1,
|
||||
|
||||
// 群聊消息
|
||||
GroupMessage = 2,
|
||||
|
||||
// 用户上线
|
||||
UserOnline = 3,
|
||||
|
||||
// 用户下线
|
||||
UserOffline = 4,
|
||||
|
||||
// 登录结果
|
||||
LoginResult = 10
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 客户端功能码
|
||||
*/
|
||||
enum ClientFunctionCode {
|
||||
// 登录
|
||||
Login = 1,
|
||||
|
||||
// 发送私聊消息
|
||||
SendPrivateMessage = 2,
|
||||
|
||||
// 发送群聊消息
|
||||
SendGroupMessage = 3
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_H
|
11
IM Porject/readme.txt
Normal file
11
IM Porject/readme.txt
Normal file
@ -0,0 +1,11 @@
|
||||
IM客户端:
|
||||
FormLogin 为登录窗口
|
||||
IMClient 为IM客户端主功能类
|
||||
IMDAL 为IM数据库
|
||||
IMMessage 为IM消息结构体
|
||||
MainWindow 为主窗体
|
||||
protocol 为通讯协议
|
||||
|
||||
IM服务端
|
||||
IMService 为IM服务端主功能类
|
||||
protocol 为通讯协议
|
Loading…
Reference in New Issue
Block a user