(broken) Merge remote-tracking branch 'upstream/master' into communities
This commit is contained in:
commit
2d592b1408
20
.ci/linux/deploy.sh
Executable file
20
.ci/linux/deploy.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p appdir
|
||||||
|
cp build/nheko appdir/
|
||||||
|
cp resources/nheko.desktop appdir/
|
||||||
|
cp resources/nheko*.png appdir/
|
||||||
|
|
||||||
|
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||||
|
chmod a+x linuxdeployqt*.AppImage
|
||||||
|
|
||||||
|
unset QTDIR
|
||||||
|
unset QT_PLUGIN_PATH
|
||||||
|
unset LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
./linuxdeployqt*.AppImage ./appdir/*.desktop -bundle-non-qt-libs
|
||||||
|
./linuxdeployqt*.AppImage ./appdir/*.desktop -appimage
|
||||||
|
|
||||||
|
chmod +x nheko-x86_64.AppImage
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
sudo add-apt-repository -y ppa:beineri/opt-qt58-trusty
|
sudo add-apt-repository -y ppa:beineri/opt-qt592-trusty
|
||||||
sudo add-apt-repository -y ppa:george-edison55/cmake-3.x
|
sudo add-apt-repository -y ppa:george-edison55/cmake-3.x
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -qq -y qt58base qt58tools cmake liblmdb-dev
|
sudo apt-get install -qq -y qt59base qt59tools cmake liblmdb-dev
|
||||||
|
11
.ci/macos/deploy.sh
Executable file
11
.ci/macos/deploy.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Add Qt binaries to path
|
||||||
|
PATH=/usr/local/opt/qt/bin/:${PATH}
|
||||||
|
|
||||||
|
sudo macdeployqt build/nheko.app -dmg
|
||||||
|
user=$(id -nu)
|
||||||
|
sudo chown ${user} build/nheko.dmg
|
||||||
|
mv build/nheko.dmg .
|
@ -1,225 +0,0 @@
|
|||||||
############################################################################################
|
|
||||||
# NSIS Installation Script created by NSIS Quick Setup Script Generator v1.09.18
|
|
||||||
# Entirely Edited with NullSoft Scriptable Installation System
|
|
||||||
# by Vlasis K. Barkas aka Red Wine red_wine@freemail.gr Sep 2006
|
|
||||||
############################################################################################
|
|
||||||
|
|
||||||
!define APP_NAME "nheko"
|
|
||||||
!define COMP_NAME "mujx"
|
|
||||||
!define WEB_SITE "https://github.com/mujx/nheko"
|
|
||||||
!define VERSION "0.1.0.0"
|
|
||||||
!define COPYRIGHT "mujx <20> 2017"
|
|
||||||
!define DESCRIPTION "Desktop client for the Matrix protocol"
|
|
||||||
!define LICENSE_TXT "LICENSE.txt"
|
|
||||||
!define INSTALLER_NAME "..\..\nheko_setup.exe"
|
|
||||||
!define INPUT_DIR "..\..\NhekoRelease"
|
|
||||||
!define MAIN_APP_EXE "nheko.exe"
|
|
||||||
!define INSTALL_TYPE "SetShellVarContext all"
|
|
||||||
!define REG_ROOT "HKLM"
|
|
||||||
!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}"
|
|
||||||
!define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
|
|
||||||
|
|
||||||
!define REG_START_MENU "Start Menu Folder"
|
|
||||||
|
|
||||||
var SM_Folder
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
VIProductVersion "${VERSION}"
|
|
||||||
VIAddVersionKey "ProductName" "${APP_NAME}"
|
|
||||||
VIAddVersionKey "CompanyName" "${COMP_NAME}"
|
|
||||||
VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
|
|
||||||
VIAddVersionKey "FileDescription" "${DESCRIPTION}"
|
|
||||||
VIAddVersionKey "FileVersion" "${VERSION}"
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
SetCompressor ZLIB
|
|
||||||
Name "${APP_NAME}"
|
|
||||||
Caption "${APP_NAME}"
|
|
||||||
OutFile "${INSTALLER_NAME}"
|
|
||||||
BrandingText "${APP_NAME}"
|
|
||||||
XPStyle on
|
|
||||||
InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" ""
|
|
||||||
InstallDir "$PROGRAMFILES\nheko"
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
!include "MUI.nsh"
|
|
||||||
|
|
||||||
!define MUI_ICON "..\..\resources\nheko.ico"
|
|
||||||
!define MUI_HEADERIMAGE
|
|
||||||
!define MUI_HEADERIMAGE_BITMAP "..\..\resources\nheko.bmp"
|
|
||||||
!define MUI_HEADERIMAGE_RIGHT
|
|
||||||
|
|
||||||
!define MUI_ABORTWARNING
|
|
||||||
!define MUI_UNABORTWARNING
|
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
|
||||||
|
|
||||||
!ifdef LICENSE_TXT
|
|
||||||
!insertmacro MUI_PAGE_LICENSE "${LICENSE_TXT}"
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
|
||||||
|
|
||||||
!ifdef REG_START_MENU
|
|
||||||
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "nheko"
|
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}"
|
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}"
|
|
||||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}"
|
|
||||||
!insertmacro MUI_PAGE_STARTMENU Application $SM_Folder
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
|
||||||
|
|
||||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
!insertmacro MUI_PAGE_FINISH
|
|
||||||
|
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
|
||||||
|
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
|
||||||
|
|
||||||
!insertmacro MUI_UNPAGE_FINISH
|
|
||||||
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
Section -MainProgram
|
|
||||||
${INSTALL_TYPE}
|
|
||||||
SetOverwrite ifnewer
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
File /r "${INPUT_DIR}\*"
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
Section -Icons_Reg
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
|
||||||
|
|
||||||
!ifdef REG_START_MENU
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
|
||||||
CreateDirectory "$SMPROGRAMS\$SM_Folder"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
|
|
||||||
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url"
|
|
||||||
!endif
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_END
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!ifndef REG_START_MENU
|
|
||||||
CreateDirectory "$SMPROGRAMS\nheko"
|
|
||||||
CreateShortCut "$SMPROGRAMS\nheko\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
CreateShortCut "$SMPROGRAMS\nheko\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
|
|
||||||
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
WriteIniStr "$INSTDIR\${APP_NAME} website.url" "InternetShortcut" "URL" "${WEB_SITE}"
|
|
||||||
CreateShortCut "$SMPROGRAMS\nheko\${APP_NAME} Website.lnk" "$INSTDIR\${APP_NAME} website.url"
|
|
||||||
!endif
|
|
||||||
!endif
|
|
||||||
|
|
||||||
WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayName" "${APP_NAME}"
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe"
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayIcon" "$INSTDIR\${MAIN_APP_EXE}"
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayVersion" "${VERSION}"
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "Publisher" "${COMP_NAME}"
|
|
||||||
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "URLInfoAbout" "${WEB_SITE}"
|
|
||||||
!endif
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
Section Uninstall
|
|
||||||
${INSTALL_TYPE}
|
|
||||||
|
|
||||||
########
|
|
||||||
|
|
||||||
!macro BadPathsCheck
|
|
||||||
StrCpy $R0 $INSTDIR "" -2
|
|
||||||
StrCmp $R0 ":\" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -14
|
|
||||||
StrCmp $R0 "\Program Files" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -8
|
|
||||||
StrCmp $R0 "\Windows" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -6
|
|
||||||
StrCmp $R0 "\WinNT" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -9
|
|
||||||
StrCmp $R0 "\system32" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -8
|
|
||||||
StrCmp $R0 "\Desktop" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -23
|
|
||||||
StrCmp $R0 "\Documents and Settings" bad
|
|
||||||
StrCpy $R0 $INSTDIR "" -13
|
|
||||||
StrCmp $R0 "\My Documents" bad done
|
|
||||||
bad:
|
|
||||||
MessageBox MB_OK|MB_ICONSTOP "Install path invalid!"
|
|
||||||
Abort
|
|
||||||
done:
|
|
||||||
!macroend
|
|
||||||
|
|
||||||
StrCmp $INSTDIR "" 0 +2
|
|
||||||
StrCpy $INSTDIR $EXEDIR
|
|
||||||
|
|
||||||
# Check that the uninstall isn't dangerous.
|
|
||||||
!insertmacro BadPathsCheck
|
|
||||||
|
|
||||||
# Does path end with "\nheko"?
|
|
||||||
!define CHECK_PATH "\nheko"
|
|
||||||
StrLen $R1 "${CHECK_PATH}"
|
|
||||||
StrCpy $R0 $INSTDIR "" -$R1
|
|
||||||
StrCmp $R0 "${CHECK_PATH}" +3
|
|
||||||
MessageBox MB_YESNO|MB_ICONQUESTION "Unrecognised uninstall path. Continue anyway?" IDYES +2
|
|
||||||
Abort
|
|
||||||
|
|
||||||
IfFileExists "$INSTDIR\*.*" 0 +2
|
|
||||||
IfFileExists "$INSTDIR\nheko.exe" +3
|
|
||||||
MessageBox MB_OK|MB_ICONSTOP "Install path invalid!"
|
|
||||||
Abort
|
|
||||||
|
|
||||||
########
|
|
||||||
|
|
||||||
RMDir /r /REBOOTOK $INSTDIR
|
|
||||||
|
|
||||||
Delete "$INSTDIR\uninstall.exe"
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
Delete "$INSTDIR\${APP_NAME} website.url"
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!ifdef REG_START_MENU
|
|
||||||
!insertmacro MUI_STARTMENU_GETFOLDER "Application" $SM_Folder
|
|
||||||
Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME}.lnk"
|
|
||||||
Delete "$SMPROGRAMS\$SM_Folder\Uninstall ${APP_NAME}.lnk"
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
Delete "$SMPROGRAMS\$SM_Folder\${APP_NAME} Website.lnk"
|
|
||||||
!endif
|
|
||||||
Delete "$DESKTOP\${APP_NAME}.lnk"
|
|
||||||
|
|
||||||
RmDir "$SMPROGRAMS\$SM_Folder"
|
|
||||||
!endif
|
|
||||||
|
|
||||||
!ifndef REG_START_MENU
|
|
||||||
Delete "$SMPROGRAMS\nheko\${APP_NAME}.lnk"
|
|
||||||
Delete "$SMPROGRAMS\nheko\Uninstall ${APP_NAME}.lnk"
|
|
||||||
!ifdef WEB_SITE
|
|
||||||
Delete "$SMPROGRAMS\nheko\${APP_NAME} Website.lnk"
|
|
||||||
!endif
|
|
||||||
Delete "$DESKTOP\${APP_NAME}.lnk"
|
|
||||||
|
|
||||||
RmDir "$SMPROGRAMS\nheko"
|
|
||||||
!endif
|
|
||||||
|
|
||||||
DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
|
|
||||||
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
######################################################################
|
|
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
|
Standard: Cpp11
|
||||||
AccessModifierOffset: -8
|
AccessModifierOffset: -8
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: true
|
AlignConsecutiveAssignments: true
|
||||||
@ -10,3 +11,4 @@ IndentCaseLabels: false
|
|||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!--
|
||||||
|
If you want to request a feature or ask a question, feel free to remove all the irrelevant text.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### System:
|
||||||
|
|
||||||
|
- Nheko commit/version:
|
||||||
|
- Operating System:
|
||||||
|
- Qt version:
|
||||||
|
- C++ compiler:
|
||||||
|
- Desktop Environment: <!-- for Linux -->
|
||||||
|
|
||||||
|
### Actual behavior
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
|
||||||
|
<!-- If the program crashed. -->
|
||||||
|
### Debugger traceback
|
28
.travis.yml
28
.travis.yml
@ -21,9 +21,33 @@ install:
|
|||||||
- if [ $TRAVIS_OS_NAME == osx ]; then export CMAKE_PREFIX_PATH=/usr/local/opt/qt5; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then export CMAKE_PREFIX_PATH=/usr/local/opt/qt5; fi
|
||||||
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/install-deps.sh; fi
|
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/install-deps.sh; fi
|
||||||
before_script:
|
before_script:
|
||||||
- if [ $TRAVIS_OS_NAME == linux ]; then source /opt/qt58/bin/qt58-env.sh; fi
|
- if [ $TRAVIS_OS_NAME == linux ]; then source /opt/qt59/bin/qt59-env.sh; fi
|
||||||
- cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
|
- cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
|
||||||
script:
|
script:
|
||||||
- make -C build -j2
|
- make -C build -j2
|
||||||
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/run-tests.sh; fi
|
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then make lint; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then make lint; fi
|
||||||
|
- if [ $TRAVIS_OS_NAME == osx ]; then ./.ci/macos/deploy.sh; fi
|
||||||
|
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/run-tests.sh; fi
|
||||||
|
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/deploy.sh; fi
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
- skip_cleanup: true
|
||||||
|
overwrite: true
|
||||||
|
provider: releases
|
||||||
|
api_key:
|
||||||
|
secure: oprXzESukFiXBeF2BXkXUlegsAQc95Ub4kc/OkoNFaYBvqpA+IGpWHmHCx5JPny/OT3Kc2Urpe2JUeGSWDHZ7UCKDjH+NzGP3uN82fHh/HiszG/Srw7+hWEHm1ve+gMK9GS8pr+yUsUrPP0UfVXlPoI4pBWa4zGi2Ndb/SqvjCgIHFLtGyoBo6CydKQ/AyWiXSMKDfJL+Dx4JLIPP4RTCBJy8ZrZ8m/a5Tgy4Ij6+djjrgYCZCEhGxSYw7xDIT/9SV8g9NkrbisqBDrILzAH8Yhe4XMRMXo88OAxV5+Vb9Rw1hrqczez6lpFDbJetv8MjofND+pSoAFwtjaL1wTFK9Ud6w4O9AuHlEQH9cGVdvsxFcosRwJVh58x51JM9ptoktqhx/HHJBTuCHCYYlHwtRwbwqnMYdLzKZG5FnujT8DG+9mcva1fL6tzW/XD505VPMWwXFC/2/pvolgAkTFFXYSALAwZlK3IgoXU8Gok/3B4iHofzQsFf6Yq3BI/88x7tVASUqiYhoKrO50+gb6pNIRCyWgGUiBEVXBp6Ziq3ORQPyQJg7i9HHUGTUu74yvGLHWLwjNQzZP/hxJZK3VlJxzyXntdOxiJc8iOzNrU+rPKBAlAaE6bQDOoniIysEgdD5BXHTLFzPvts4P1n2Ckor5/rNJ+qXR8GU+/y7e1GKU=
|
||||||
|
file: nheko-x86_64.AppImage
|
||||||
|
on:
|
||||||
|
condition: $TRAVIS_OS_NAME == linux
|
||||||
|
repo: mujx/nheko
|
||||||
|
tags: true
|
||||||
|
- skip_cleanup: true
|
||||||
|
overwrite: true
|
||||||
|
provider: releases
|
||||||
|
api_key:
|
||||||
|
secure: oprXzESukFiXBeF2BXkXUlegsAQc95Ub4kc/OkoNFaYBvqpA+IGpWHmHCx5JPny/OT3Kc2Urpe2JUeGSWDHZ7UCKDjH+NzGP3uN82fHh/HiszG/Srw7+hWEHm1ve+gMK9GS8pr+yUsUrPP0UfVXlPoI4pBWa4zGi2Ndb/SqvjCgIHFLtGyoBo6CydKQ/AyWiXSMKDfJL+Dx4JLIPP4RTCBJy8ZrZ8m/a5Tgy4Ij6+djjrgYCZCEhGxSYw7xDIT/9SV8g9NkrbisqBDrILzAH8Yhe4XMRMXo88OAxV5+Vb9Rw1hrqczez6lpFDbJetv8MjofND+pSoAFwtjaL1wTFK9Ud6w4O9AuHlEQH9cGVdvsxFcosRwJVh58x51JM9ptoktqhx/HHJBTuCHCYYlHwtRwbwqnMYdLzKZG5FnujT8DG+9mcva1fL6tzW/XD505VPMWwXFC/2/pvolgAkTFFXYSALAwZlK3IgoXU8Gok/3B4iHofzQsFf6Yq3BI/88x7tVASUqiYhoKrO50+gb6pNIRCyWgGUiBEVXBp6Ziq3ORQPyQJg7i9HHUGTUu74yvGLHWLwjNQzZP/hxJZK3VlJxzyXntdOxiJc8iOzNrU+rPKBAlAaE6bQDOoniIysEgdD5BXHTLFzPvts4P1n2Ckor5/rNJ+qXR8GU+/y7e1GKU=
|
||||||
|
file: nheko.dmg
|
||||||
|
on:
|
||||||
|
condition: $TRAVIS_OS_NAME == osx
|
||||||
|
repo: mujx/nheko
|
||||||
|
tags: true
|
||||||
|
810
.vscode/.cmaketools.json
vendored
Normal file
810
.vscode/.cmaketools.json
vendored
Normal file
@ -0,0 +1,810 @@
|
|||||||
|
{
|
||||||
|
"variant": {
|
||||||
|
"label": "Debug",
|
||||||
|
"keywordSettings": {
|
||||||
|
"buildType": "debug"
|
||||||
|
},
|
||||||
|
"description": "Emit debug information without performing optimizations"
|
||||||
|
},
|
||||||
|
"activeEnvironments": [],
|
||||||
|
"codeModel": {
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug",
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"buildDirectory": "/home/max/Program/nheko/build",
|
||||||
|
"name": "nheko",
|
||||||
|
"sourceDirectory": "/home/max/Program/nheko",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"artifacts": [
|
||||||
|
"/home/max/Program/nheko/build/nheko"
|
||||||
|
],
|
||||||
|
"buildDirectory": "/home/max/Program/nheko/build",
|
||||||
|
"crossReferences": {
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 355,
|
||||||
|
"name": "add_executable",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relatedStatements": [
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 233,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 234,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 235,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 236,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 238,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 239,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 356,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 356,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 356,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 356,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 356,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fileGroups": [
|
||||||
|
{
|
||||||
|
"isGenerated": false,
|
||||||
|
"sources": [
|
||||||
|
"resources/res.qrc",
|
||||||
|
"build/translations.qrc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compileFlags": " -Wall -Wextra -march=native -Werror -pipe -pedantic -Wunreachable-code -fdiagnostics-color=always -g -fPIC -std=gnu++11",
|
||||||
|
"defines": [
|
||||||
|
"QT_CONCURRENT_LIB",
|
||||||
|
"QT_CORE_LIB",
|
||||||
|
"QT_GUI_LIB",
|
||||||
|
"QT_NETWORK_LIB",
|
||||||
|
"QT_WIDGETS_LIB"
|
||||||
|
],
|
||||||
|
"includePath": [
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events/messages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/libs/lmdbxx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtCore"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/lib64/qt5/./mkspecs/linux-g++"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtWidgets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtGui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtNetwork"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtConcurrent"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isGenerated": false,
|
||||||
|
"language": "CXX",
|
||||||
|
"sources": [
|
||||||
|
"src/AvatarProvider.cc",
|
||||||
|
"src/Cache.cc",
|
||||||
|
"src/ChatPage.cc",
|
||||||
|
"src/CommunitiesListItem.cc",
|
||||||
|
"src/CommunitiesList.cc",
|
||||||
|
"src/Community.cc",
|
||||||
|
"src/Deserializable.cc",
|
||||||
|
"src/EmojiCategory.cc",
|
||||||
|
"src/EmojiItemDelegate.cc",
|
||||||
|
"src/EmojiPanel.cc",
|
||||||
|
"src/EmojiPickButton.cc",
|
||||||
|
"src/EmojiProvider.cc",
|
||||||
|
"src/ImageItem.cc",
|
||||||
|
"src/ImageOverlayDialog.cc",
|
||||||
|
"src/InputValidator.cc",
|
||||||
|
"src/JoinRoomDialog.cc",
|
||||||
|
"src/LeaveRoomDialog.cc",
|
||||||
|
"src/Login.cc",
|
||||||
|
"src/LoginPage.cc",
|
||||||
|
"src/LogoutDialog.cc",
|
||||||
|
"src/MainWindow.cc",
|
||||||
|
"src/MatrixClient.cc",
|
||||||
|
"src/Profile.cc",
|
||||||
|
"src/QuickSwitcher.cc",
|
||||||
|
"src/Register.cc",
|
||||||
|
"src/RegisterPage.cc",
|
||||||
|
"src/RoomInfoListItem.cc",
|
||||||
|
"src/RoomList.cc",
|
||||||
|
"src/RoomMessages.cc",
|
||||||
|
"src/RoomState.cc",
|
||||||
|
"src/SideBarActions.cc",
|
||||||
|
"src/UserSettingsPage.cc",
|
||||||
|
"src/Splitter.cc",
|
||||||
|
"src/Sync.cc",
|
||||||
|
"src/TextInputWidget.cc",
|
||||||
|
"src/TimelineItem.cc",
|
||||||
|
"src/TimelineView.cc",
|
||||||
|
"src/TimelineViewManager.cc",
|
||||||
|
"src/TopRoomBar.cc",
|
||||||
|
"src/TrayIcon.cc",
|
||||||
|
"src/TypingDisplay.cc",
|
||||||
|
"src/UserInfoWidget.cc",
|
||||||
|
"src/Versions.cc",
|
||||||
|
"src/WelcomePage.cc",
|
||||||
|
"src/main.cc",
|
||||||
|
"src/ui/Avatar.cc",
|
||||||
|
"src/ui/Badge.cc",
|
||||||
|
"src/ui/LoadingIndicator.cc",
|
||||||
|
"src/ui/FlatButton.cc",
|
||||||
|
"src/ui/FloatingButton.cc",
|
||||||
|
"src/ui/Label.cc",
|
||||||
|
"src/ui/OverlayModal.cc",
|
||||||
|
"src/ui/ScrollBar.cc",
|
||||||
|
"src/ui/SnackBar.cc",
|
||||||
|
"src/ui/RaisedButton.cc",
|
||||||
|
"src/ui/Ripple.cc",
|
||||||
|
"src/ui/RippleOverlay.cc",
|
||||||
|
"src/ui/OverlayWidget.cc",
|
||||||
|
"src/ui/TextField.cc",
|
||||||
|
"src/ui/ToggleButton.cc",
|
||||||
|
"src/ui/Theme.cc",
|
||||||
|
"src/ui/ThemeManager.cc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated": true,
|
||||||
|
"sources": [
|
||||||
|
"build/nheko_de.qm",
|
||||||
|
"build/nheko_el.qm",
|
||||||
|
"build/nheko_en.qm",
|
||||||
|
"build/nheko_nl.qm",
|
||||||
|
"build/include/moc_AvatarProvider.cpp.rule",
|
||||||
|
"build/include/moc_ChatPage.cpp.rule",
|
||||||
|
"build/include/moc_CommunitiesListItem.cpp.rule",
|
||||||
|
"build/include/moc_CommunitiesList.cpp.rule",
|
||||||
|
"build/include/moc_Community.cpp.rule",
|
||||||
|
"build/include/moc_EmojiCategory.cpp.rule",
|
||||||
|
"build/include/moc_EmojiItemDelegate.cpp.rule",
|
||||||
|
"build/include/moc_EmojiPanel.cpp.rule",
|
||||||
|
"build/include/moc_EmojiPickButton.cpp.rule",
|
||||||
|
"build/include/ui/moc_FloatingButton.cpp.rule",
|
||||||
|
"build/include/moc_ImageItem.cpp.rule",
|
||||||
|
"build/include/moc_ImageOverlayDialog.cpp.rule",
|
||||||
|
"build/include/moc_JoinRoomDialog.cpp.rule",
|
||||||
|
"build/include/moc_LeaveRoomDialog.cpp.rule",
|
||||||
|
"build/include/moc_LoginPage.cpp.rule",
|
||||||
|
"build/include/moc_LogoutDialog.cpp.rule",
|
||||||
|
"build/include/moc_MainWindow.cpp.rule",
|
||||||
|
"build/include/moc_MatrixClient.cpp.rule",
|
||||||
|
"build/include/moc_QuickSwitcher.cpp.rule",
|
||||||
|
"build/include/moc_RegisterPage.cpp.rule",
|
||||||
|
"build/include/moc_RoomInfoListItem.cpp.rule",
|
||||||
|
"build/include/moc_RoomList.cpp.rule",
|
||||||
|
"build/include/moc_SideBarActions.cpp.rule",
|
||||||
|
"build/include/moc_UserSettingsPage.cpp.rule",
|
||||||
|
"build/include/moc_Splitter.cpp.rule",
|
||||||
|
"build/include/moc_TextInputWidget.cpp.rule",
|
||||||
|
"build/include/moc_TimelineItem.cpp.rule",
|
||||||
|
"build/include/moc_TimelineView.cpp.rule",
|
||||||
|
"build/include/moc_TimelineViewManager.cpp.rule",
|
||||||
|
"build/include/moc_TopRoomBar.cpp.rule",
|
||||||
|
"build/include/moc_TrayIcon.cpp.rule",
|
||||||
|
"build/include/moc_TypingDisplay.cpp.rule",
|
||||||
|
"build/include/moc_UserInfoWidget.cpp.rule",
|
||||||
|
"build/include/moc_WelcomePage.cpp.rule",
|
||||||
|
"build/include/ui/moc_Avatar.cpp.rule",
|
||||||
|
"build/include/ui/moc_Badge.cpp.rule",
|
||||||
|
"build/include/ui/moc_LoadingIndicator.cpp.rule",
|
||||||
|
"build/include/ui/moc_FlatButton.cpp.rule",
|
||||||
|
"build/include/ui/moc_Label.cpp.rule",
|
||||||
|
"build/include/ui/moc_OverlayWidget.cpp.rule",
|
||||||
|
"build/include/ui/moc_ScrollBar.cpp.rule",
|
||||||
|
"build/include/ui/moc_SnackBar.cpp.rule",
|
||||||
|
"build/include/ui/moc_RaisedButton.cpp.rule",
|
||||||
|
"build/include/ui/moc_Ripple.cpp.rule",
|
||||||
|
"build/include/ui/moc_RippleOverlay.cpp.rule",
|
||||||
|
"build/include/ui/moc_TextField.cpp.rule",
|
||||||
|
"build/include/ui/moc_ToggleButton.cpp.rule",
|
||||||
|
"build/include/ui/moc_Theme.cpp.rule",
|
||||||
|
"build/include/ui/moc_ThemeManager.cpp.rule",
|
||||||
|
"build/nheko_de.qm.rule",
|
||||||
|
"build/nheko_el.qm.rule",
|
||||||
|
"build/nheko_en.qm.rule",
|
||||||
|
"build/nheko_nl.qm.rule"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compileFlags": " -Wall -Wextra -march=native -Werror -pipe -pedantic -Wunreachable-code -fdiagnostics-color=always -g -fPIC -std=gnu++11",
|
||||||
|
"defines": [
|
||||||
|
"QT_CONCURRENT_LIB",
|
||||||
|
"QT_CORE_LIB",
|
||||||
|
"QT_GUI_LIB",
|
||||||
|
"QT_NETWORK_LIB",
|
||||||
|
"QT_WIDGETS_LIB"
|
||||||
|
],
|
||||||
|
"includePath": [
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events/messages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/libs/lmdbxx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtCore"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/lib64/qt5/./mkspecs/linux-g++"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtWidgets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtGui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtNetwork"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtConcurrent"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isGenerated": true,
|
||||||
|
"language": "CXX",
|
||||||
|
"sources": [
|
||||||
|
"build/include/moc_AvatarProvider.cpp",
|
||||||
|
"build/include/moc_ChatPage.cpp",
|
||||||
|
"build/include/moc_CommunitiesListItem.cpp",
|
||||||
|
"build/include/moc_CommunitiesList.cpp",
|
||||||
|
"build/include/moc_Community.cpp",
|
||||||
|
"build/include/moc_EmojiCategory.cpp",
|
||||||
|
"build/include/moc_EmojiItemDelegate.cpp",
|
||||||
|
"build/include/moc_EmojiPanel.cpp",
|
||||||
|
"build/include/moc_EmojiPickButton.cpp",
|
||||||
|
"build/include/ui/moc_FloatingButton.cpp",
|
||||||
|
"build/include/moc_ImageItem.cpp",
|
||||||
|
"build/include/moc_ImageOverlayDialog.cpp",
|
||||||
|
"build/include/moc_JoinRoomDialog.cpp",
|
||||||
|
"build/include/moc_LeaveRoomDialog.cpp",
|
||||||
|
"build/include/moc_LoginPage.cpp",
|
||||||
|
"build/include/moc_LogoutDialog.cpp",
|
||||||
|
"build/include/moc_MainWindow.cpp",
|
||||||
|
"build/include/moc_MatrixClient.cpp",
|
||||||
|
"build/include/moc_QuickSwitcher.cpp",
|
||||||
|
"build/include/moc_RegisterPage.cpp",
|
||||||
|
"build/include/moc_RoomInfoListItem.cpp",
|
||||||
|
"build/include/moc_RoomList.cpp",
|
||||||
|
"build/include/moc_SideBarActions.cpp",
|
||||||
|
"build/include/moc_UserSettingsPage.cpp",
|
||||||
|
"build/include/moc_Splitter.cpp",
|
||||||
|
"build/include/moc_TextInputWidget.cpp",
|
||||||
|
"build/include/moc_TimelineItem.cpp",
|
||||||
|
"build/include/moc_TimelineView.cpp",
|
||||||
|
"build/include/moc_TimelineViewManager.cpp",
|
||||||
|
"build/include/moc_TopRoomBar.cpp",
|
||||||
|
"build/include/moc_TrayIcon.cpp",
|
||||||
|
"build/include/moc_TypingDisplay.cpp",
|
||||||
|
"build/include/moc_UserInfoWidget.cpp",
|
||||||
|
"build/include/moc_WelcomePage.cpp",
|
||||||
|
"build/include/ui/moc_Avatar.cpp",
|
||||||
|
"build/include/ui/moc_Badge.cpp",
|
||||||
|
"build/include/ui/moc_LoadingIndicator.cpp",
|
||||||
|
"build/include/ui/moc_FlatButton.cpp",
|
||||||
|
"build/include/ui/moc_Label.cpp",
|
||||||
|
"build/include/ui/moc_OverlayWidget.cpp",
|
||||||
|
"build/include/ui/moc_ScrollBar.cpp",
|
||||||
|
"build/include/ui/moc_SnackBar.cpp",
|
||||||
|
"build/include/ui/moc_RaisedButton.cpp",
|
||||||
|
"build/include/ui/moc_Ripple.cpp",
|
||||||
|
"build/include/ui/moc_RippleOverlay.cpp",
|
||||||
|
"build/include/ui/moc_TextField.cpp",
|
||||||
|
"build/include/ui/moc_ToggleButton.cpp",
|
||||||
|
"build/include/ui/moc_Theme.cpp",
|
||||||
|
"build/include/ui/moc_ThemeManager.cpp",
|
||||||
|
"build/qrc_res.cpp",
|
||||||
|
"build/qrc_translations.cpp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fullName": "nheko",
|
||||||
|
"linkFlags": "-rdynamic",
|
||||||
|
"linkLanguageFlags": "-Wall -Wextra -march=native -Werror -pipe -pedantic -Wunreachable-code -fdiagnostics-color=always -g",
|
||||||
|
"linkLibraries": "libmatrix_events.a /usr/lib64/libQt5Widgets.so.5.9.2 /usr/lib64/libQt5Network.so.5.9.2 /usr/lib64/libQt5Concurrent.so.5.9.2 -llmdb /usr/lib64/libQt5Gui.so.5.9.2 /usr/lib64/libQt5Core.so.5.9.2",
|
||||||
|
"linkerLanguage": "CXX",
|
||||||
|
"name": "nheko",
|
||||||
|
"sourceDirectory": "/home/max/Program/nheko",
|
||||||
|
"type": "EXECUTABLE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buildDirectory": "/home/max/Program/nheko/build",
|
||||||
|
"crossReferences": {
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 300,
|
||||||
|
"name": "add_custom_target",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relatedStatements": [
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 233,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 234,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 235,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 236,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 238,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 239,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fileGroups": [
|
||||||
|
{
|
||||||
|
"isGenerated": true,
|
||||||
|
"sources": [
|
||||||
|
"build/CMakeFiles/LANG_QRC",
|
||||||
|
"build/CMakeFiles/LANG_QRC.rule",
|
||||||
|
"build/nheko_de.qm.rule",
|
||||||
|
"build/nheko_el.qm.rule",
|
||||||
|
"build/nheko_en.qm.rule",
|
||||||
|
"build/nheko_nl.qm.rule"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fullName": "LANG_QRC",
|
||||||
|
"name": "LANG_QRC",
|
||||||
|
"sourceDirectory": "/home/max/Program/nheko",
|
||||||
|
"type": "UTILITY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"artifacts": [
|
||||||
|
"/home/max/Program/nheko/build/libmatrix_events.a"
|
||||||
|
],
|
||||||
|
"buildDirectory": "/home/max/Program/nheko/build",
|
||||||
|
"crossReferences": {
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 317,
|
||||||
|
"name": "add_library",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relatedStatements": [
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 233,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 234,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 235,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 236,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 238,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 239,
|
||||||
|
"name": "include_directories",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_include_directories"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace": [
|
||||||
|
{
|
||||||
|
"line": 318,
|
||||||
|
"name": "target_link_libraries",
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "target_link_libraries"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fileGroups": [
|
||||||
|
{
|
||||||
|
"compileFlags": " -Wall -Wextra -march=native -Werror -pipe -pedantic -Wunreachable-code -fdiagnostics-color=always -g -fPIC -std=gnu++11",
|
||||||
|
"defines": [
|
||||||
|
"QT_CORE_LIB"
|
||||||
|
],
|
||||||
|
"includePath": [
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/include/events/messages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/home/max/Program/nheko/libs/lmdbxx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/include/qt5/QtCore"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isSystem": true,
|
||||||
|
"path": "/usr/lib64/qt5/./mkspecs/linux-g++"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isGenerated": false,
|
||||||
|
"language": "CXX",
|
||||||
|
"sources": [
|
||||||
|
"src/events/Event.cc",
|
||||||
|
"src/events/AliasesEventContent.cc",
|
||||||
|
"src/events/AvatarEventContent.cc",
|
||||||
|
"src/events/CanonicalAliasEventContent.cc",
|
||||||
|
"src/events/CreateEventContent.cc",
|
||||||
|
"src/events/HistoryVisibilityEventContent.cc",
|
||||||
|
"src/events/JoinRulesEventContent.cc",
|
||||||
|
"src/events/MemberEventContent.cc",
|
||||||
|
"src/events/MessageEventContent.cc",
|
||||||
|
"src/events/NameEventContent.cc",
|
||||||
|
"src/events/PowerLevelsEventContent.cc",
|
||||||
|
"src/events/TopicEventContent.cc",
|
||||||
|
"src/events/messages/Audio.cc",
|
||||||
|
"src/events/messages/Emote.cc",
|
||||||
|
"src/events/messages/File.cc",
|
||||||
|
"src/events/messages/Image.cc",
|
||||||
|
"src/events/messages/Location.cc",
|
||||||
|
"src/events/messages/Notice.cc",
|
||||||
|
"src/events/messages/Text.cc",
|
||||||
|
"src/events/messages/Video.cc",
|
||||||
|
"src/Deserializable.cc"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fullName": "libmatrix_events.a",
|
||||||
|
"linkerLanguage": "CXX",
|
||||||
|
"name": "matrix_events",
|
||||||
|
"sourceDirectory": "/home/max/Program/nheko",
|
||||||
|
"type": "STATIC_LIBRARY"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": "0.46582309898312313",
|
||||||
|
"inReplyTo": "codemodel",
|
||||||
|
"type": "reply"
|
||||||
|
}
|
||||||
|
}
|
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "null",
|
||||||
|
"includePath": [],
|
||||||
|
"defines": [],
|
||||||
|
"browse": {
|
||||||
|
"path": [],
|
||||||
|
"limitSymbolsToIncludedHeaders": true,
|
||||||
|
"databaseFilename": ""
|
||||||
|
},
|
||||||
|
"intelliSenseMode": "clang-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 3
|
||||||
|
}
|
12
.vscode/tasks.json
vendored
Normal file
12
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "echo",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "echo Hello"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,10 +1,25 @@
|
|||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
project(nheko C CXX)
|
|
||||||
|
|
||||||
option(BUILD_TESTS "Build all tests" OFF)
|
option(BUILD_TESTS "Build all tests" OFF)
|
||||||
option(APPVEYOR_BUILD "Build on appveyor" OFF)
|
option(APPVEYOR_BUILD "Build on appveyor" OFF)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
# Include Qt basic functions
|
||||||
|
include(QtCommon)
|
||||||
|
|
||||||
|
project(nheko LANGUAGES C CXX VERSION 0.1.0)
|
||||||
|
|
||||||
|
# Set PROJECT_VERSION_PATCH and PROJECT_VERSION_TWEAK to 0 if not present, needed by add_project_meta
|
||||||
|
fix_project_version()
|
||||||
|
|
||||||
|
# Set additional project information
|
||||||
|
set(COMPANY "Nheko")
|
||||||
|
set(COPYRIGHT "Copyright (c) 2017 Mujx")
|
||||||
|
set(IDENTIFIER "com.mujx.nheko")
|
||||||
|
|
||||||
|
add_project_meta(META_FILES_TO_INCLUDE)
|
||||||
|
|
||||||
#
|
#
|
||||||
# LMDB
|
# LMDB
|
||||||
#
|
#
|
||||||
@ -156,6 +171,7 @@ set(SRC_FILES
|
|||||||
src/RoomMessages.cc
|
src/RoomMessages.cc
|
||||||
src/RoomState.cc
|
src/RoomState.cc
|
||||||
src/SideBarActions.cc
|
src/SideBarActions.cc
|
||||||
|
src/UserSettingsPage.cc
|
||||||
src/Splitter.cc
|
src/Splitter.cc
|
||||||
src/Sync.cc
|
src/Sync.cc
|
||||||
src/TextInputWidget.cc
|
src/TextInputWidget.cc
|
||||||
@ -184,6 +200,7 @@ set(SRC_FILES
|
|||||||
src/ui/RippleOverlay.cc
|
src/ui/RippleOverlay.cc
|
||||||
src/ui/OverlayWidget.cc
|
src/ui/OverlayWidget.cc
|
||||||
src/ui/TextField.cc
|
src/ui/TextField.cc
|
||||||
|
src/ui/ToggleButton.cc
|
||||||
src/ui/Theme.cc
|
src/ui/Theme.cc
|
||||||
src/ui/ThemeManager.cc
|
src/ui/ThemeManager.cc
|
||||||
)
|
)
|
||||||
@ -245,6 +262,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
include/RoomInfoListItem.h
|
include/RoomInfoListItem.h
|
||||||
include/RoomList.h
|
include/RoomList.h
|
||||||
include/SideBarActions.h
|
include/SideBarActions.h
|
||||||
|
include/UserSettingsPage.h
|
||||||
include/Splitter.h
|
include/Splitter.h
|
||||||
include/TextInputWidget.h
|
include/TextInputWidget.h
|
||||||
include/TimelineItem.h
|
include/TimelineItem.h
|
||||||
@ -268,6 +286,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
include/ui/Ripple.h
|
include/ui/Ripple.h
|
||||||
include/ui/RippleOverlay.h
|
include/ui/RippleOverlay.h
|
||||||
include/ui/TextField.h
|
include/ui/TextField.h
|
||||||
|
include/ui/ToggleButton.h
|
||||||
include/ui/Theme.h
|
include/ui/Theme.h
|
||||||
include/ui/ThemeManager.h
|
include/ui/ThemeManager.h
|
||||||
)
|
)
|
||||||
@ -298,14 +317,6 @@ qt5_add_resources(QRC resources/res.qrc)
|
|||||||
add_library(matrix_events ${MATRIX_EVENTS} src/Deserializable.cc)
|
add_library(matrix_events ${MATRIX_EVENTS} src/Deserializable.cc)
|
||||||
target_link_libraries(matrix_events Qt5::Core)
|
target_link_libraries(matrix_events Qt5::Core)
|
||||||
|
|
||||||
#
|
|
||||||
# Bundle icons.
|
|
||||||
#
|
|
||||||
if (APPLE)
|
|
||||||
set(ICON_FILE resources/nheko.icns)
|
|
||||||
set_source_files_properties(${ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_TESTS)
|
if (BUILD_TESTS)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
@ -332,15 +343,15 @@ else()
|
|||||||
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network Qt5::Concurrent ${LMDB_LIBRARY})
|
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network Qt5::Concurrent ${LMDB_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set (NHEKO_DEPS ${OS_BUNDLE} ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC})
|
set (NHEKO_DEPS ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC} ${META_FILES_TO_INCLUDE})
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_executable (nheko ${NHEKO_DEPS})
|
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
|
||||||
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
|
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
add_executable (nheko ${ICON_FILE} ${NHEKO_DEPS})
|
add_executable (nheko ${OS_BUNDLE} ${ICON_FILE} ${NHEKO_DEPS})
|
||||||
target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain)
|
target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain)
|
||||||
else()
|
else()
|
||||||
add_executable (nheko ${NHEKO_DEPS})
|
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
|
||||||
target_link_libraries (nheko ${NHEKO_LIBS})
|
target_link_libraries (nheko ${NHEKO_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
22
Makefile
22
Makefile
@ -1,9 +1,4 @@
|
|||||||
APP_NAME = nheko
|
|
||||||
|
|
||||||
MAC_DIST_DIR = dist/MacOS
|
|
||||||
APP_TEMPLATE = $(MAC_DIST_DIR)/Nheko.app
|
|
||||||
|
|
||||||
# Linux specific helpers
|
|
||||||
debug:
|
debug:
|
||||||
@cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug
|
@cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug
|
||||||
@cmake --build build
|
@cmake --build build
|
||||||
@ -17,19 +12,14 @@ test:
|
|||||||
@cmake --build build
|
@cmake --build build
|
||||||
@cd build && GTEST_COLOR=1 ctest --verbose
|
@cd build && GTEST_COLOR=1 ctest --verbose
|
||||||
|
|
||||||
app: release-debug $(APP_TEMPLATE)
|
linux-appimage:
|
||||||
@cp -fp ./build/$(APP_NAME) $(APP_TEMPLATE)/Contents/MacOS
|
@./.ci/linux/deploy.sh
|
||||||
@echo "Created '$(APP_NAME).app' in '$(APP_TEMPLATE)'"
|
|
||||||
|
|
||||||
app-install: app
|
macos-app: release-debug
|
||||||
cp -Rf $(APP_TEMPLATE) /Applications/
|
@./.ci/macos/deploy.sh
|
||||||
|
|
||||||
dmg: app
|
macos-app-install:
|
||||||
hdiutil create $(MAC_DIST_DIR)/Nheko.dmg \
|
cp -Rf build/nheko.app /Applications
|
||||||
-volname "$(APP_NAME)" \
|
|
||||||
-fs HFS+ \
|
|
||||||
-srcfolder $(MAC_DIST_DIR) \
|
|
||||||
-ov -format UDZO
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@./build/nheko
|
@./build/nheko
|
||||||
|
18
README.md
18
README.md
@ -16,10 +16,12 @@ but we are getting close to a more feature complete client.
|
|||||||
Specifically there is support for:
|
Specifically there is support for:
|
||||||
- Joining & leaving rooms
|
- Joining & leaving rooms
|
||||||
- Sending & receiving images and emoji.
|
- Sending & receiving images and emoji.
|
||||||
- Receiving typing notifications.
|
- Typing notifications.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
|
There are pre-built nigtly releases [here](https://github.com/mujx/nheko/releases/tag/nightly) for Linux ([AppImage](https://appimage.org/)), Mac and Windows.
|
||||||
|
|
||||||
#### Arch Linux
|
#### Arch Linux
|
||||||
```bash
|
```bash
|
||||||
pacaur -S nheko-git
|
pacaur -S nheko-git
|
||||||
@ -37,10 +39,6 @@ sudo layman -a matrix
|
|||||||
sudo emerge -a nheko
|
sudo emerge -a nheko
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows
|
|
||||||
|
|
||||||
You can find an installer [here](https://ci.appveyor.com/project/mujx/nheko/branch/master/artifacts).
|
|
||||||
|
|
||||||
### Build Requirements
|
### Build Requirements
|
||||||
|
|
||||||
- Qt5 (5.7 or greater). Qt 5.7 adds support for color font rendering with
|
- Qt5 (5.7 or greater). Qt 5.7 adds support for color font rendering with
|
||||||
@ -105,15 +103,7 @@ make -C build
|
|||||||
|
|
||||||
The `nheko` binary will be located in the `build` directory.
|
The `nheko` binary will be located in the `build` directory.
|
||||||
|
|
||||||
##### MacOS
|
#### Nix
|
||||||
|
|
||||||
You can create an app bundle with `make app`. The output will be located at
|
|
||||||
`dist/MacOS/Nheko.app` which can be copied to `/Applications/Nheko.app`.
|
|
||||||
|
|
||||||
You can also create a disk image with `make dmg`. The output will be located at
|
|
||||||
`dist/MacOS/Nheko.dmg`
|
|
||||||
|
|
||||||
##### Nix
|
|
||||||
|
|
||||||
Download the repo as mentioned above and run
|
Download the repo as mentioned above and run
|
||||||
|
|
||||||
|
79
appveyor.yml
79
appveyor.yml
@ -15,14 +15,32 @@ build:
|
|||||||
install:
|
install:
|
||||||
- set QT_DIR=C:\Qt\5.8\msvc2015_64
|
- set QT_DIR=C:\Qt\5.8\msvc2015_64
|
||||||
- set PATH=%PATH%;%QT_DIR%\bin;C:\MinGW\bin
|
- set PATH=%PATH%;%QT_DIR%\bin;C:\MinGW\bin
|
||||||
- copy LICENSE .ci\windows\LICENSE.txt
|
|
||||||
- cinst nsis --version 3.0 -y -installArgs /D=C:\nsis
|
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmake -G "Visual Studio 14 2015 Win64" -H. -Bbuild -DAPPVEYOR_BUILD=ON
|
# VERSION format: branch-master/branch-1.2
|
||||||
|
# INSTVERSION format: x.y.z
|
||||||
|
# WINVERSION format: 9999.0.0.123/1.2.0.234
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="false" set INSTVERSION=0.1.0
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="false" set VERSION=0.1.0
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="false" if "%APPVEYOR_REPO_BRANCH%"=="master" set INSTVERSION=9999.0
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="false" set WINVERSION=%INSTVERSION%.0.%APPVEYOR_BUILD_NUMBER%
|
||||||
|
# VERSION format: v1.2.3/v1.3.4
|
||||||
|
# INSTVERSION format: 1.2.3/1.3.4
|
||||||
|
# WINVERSION format: 1.2.3.123/1.3.4.234
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="true" set VERSION=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="true" set INSTVERSION=%VERSION:~1%
|
||||||
|
- if "%APPVEYOR_REPO_TAG%"=="true" set WINVERSION=%VERSION:~1%.%APPVEYOR_BUILD_NUMBER%
|
||||||
|
- set DATE=%date:~10,4%-%date:~4,2%-%date:~7,2%
|
||||||
|
- echo %VERSION%
|
||||||
|
- echo %INSTVERSION%
|
||||||
|
- echo %DATE%
|
||||||
|
- cmake -G "Visual Studio 14 2015 Win64" -H. -Bbuild -DAPPVEYOR_BUILD=ON -DCMAKE_BUILD_TYPE=Release
|
||||||
- cmake --build build --config Release
|
- cmake --build build --config Release
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
|
# Variables
|
||||||
|
- set BUILD=%APPVEYOR_BUILD_FOLDER%
|
||||||
|
- echo %BUILD%
|
||||||
- mkdir NhekoRelease
|
- mkdir NhekoRelease
|
||||||
- copy build\Release\nheko.exe NhekoRelease\nheko.exe
|
- copy build\Release\nheko.exe NhekoRelease\nheko.exe
|
||||||
- windeployqt --qmldir C:\Qt\5.8\msvc2015_64\qml\ --release NhekoRelease\nheko.exe
|
- windeployqt --qmldir C:\Qt\5.8\msvc2015_64\qml\ --release NhekoRelease\nheko.exe
|
||||||
@ -31,9 +49,58 @@ after_build:
|
|||||||
- copy C:\OpenSSL-Win64\lib\libeay32.lib .\NhekoRelease\libeay32.lib
|
- copy C:\OpenSSL-Win64\lib\libeay32.lib .\NhekoRelease\libeay32.lib
|
||||||
- copy C:\OpenSSL-Win64\bin\ssleay32.dll .\NhekoRelease\ssleay32.dll
|
- copy C:\OpenSSL-Win64\bin\ssleay32.dll .\NhekoRelease\ssleay32.dll
|
||||||
- 7z a nheko_win_64.zip .\NhekoRelease\*
|
- 7z a nheko_win_64.zip .\NhekoRelease\*
|
||||||
- C:\nsis\makensis .ci\windows\nheko.nsi
|
- ls -lh build\Release\
|
||||||
|
- ls -lh NhekoRelease\
|
||||||
|
- mkdir NhekoData
|
||||||
|
- xcopy .\NhekoRelease\*.* NhekoData\*.* /s /e /c /y
|
||||||
|
#
|
||||||
|
# Create the Qt Installer Framework version
|
||||||
|
#
|
||||||
|
- mkdir installer
|
||||||
|
- mkdir installer\config
|
||||||
|
- mkdir installer\packages
|
||||||
|
- mkdir installer\packages\com.mujx.nheko
|
||||||
|
- mkdir installer\packages\com.mujx.nheko\data
|
||||||
|
- mkdir installer\packages\com.mujx.nheko\meta
|
||||||
|
- mkdir installer\packages\com.mujx.nheko.cleanup\meta
|
||||||
|
# Copy installer data
|
||||||
|
- copy %BUILD%\resources\nheko.ico installer\config
|
||||||
|
- copy %BUILD%\resources\nheko.png installer\config
|
||||||
|
- copy %BUILD%\LICENSE installer\packages\com.mujx.nheko\meta\license.txt
|
||||||
|
- copy %BUILD%\LICENSE installer\packages\com.mujx.nheko.cleanup\meta\license.txt
|
||||||
|
- copy %BUILD%\deploy\installer\config.xml installer\config
|
||||||
|
- copy %BUILD%\deploy\installer\controlscript.qs installer\config
|
||||||
|
- copy %BUILD%\deploy\installer\uninstall.qs installer\packages\com.mujx.nheko\data
|
||||||
|
- copy %BUILD%\deploy\installer\gui\package.xml installer\packages\com.mujx.nheko\meta
|
||||||
|
- copy %BUILD%\deploy\installer\gui\installscript.qs installer\packages\com.mujx.nheko\meta
|
||||||
|
- copy %BUILD%\deploy\installer\cleanup\package.xml installer\packages\com.mujx.nheko.cleanup\meta
|
||||||
|
- copy %BUILD%\deploy\installer\cleanup\installscript.qs installer\packages\com.mujx.nheko.cleanup\meta
|
||||||
|
# Amend version and date
|
||||||
|
- sed -i "s/__VERSION__/0.1.0/" installer\config\config.xml
|
||||||
|
- sed -i "s/__VERSION__/0.1.0/" installer\packages\com.mujx.nheko\meta\package.xml
|
||||||
|
- sed -i "s/__VERSION__/0.1.0/" installer\packages\com.mujx.nheko.cleanup\meta\package.xml
|
||||||
|
- sed -i "s/__DATE__/%DATE%/" installer\packages\com.mujx.nheko\meta\package.xml
|
||||||
|
- sed -i "s/__DATE__/%DATE%/" installer\packages\com.mujx.nheko.cleanup\meta\package.xml
|
||||||
|
# Copy nheko data
|
||||||
|
- xcopy NhekoData\*.* installer\packages\com.mujx.nheko\data\*.* /s /e /c /y
|
||||||
|
- move NhekoRelease\nheko.exe installer\packages\com.mujx.nheko\data
|
||||||
|
- mkdir tools
|
||||||
|
- curl -L -O https://download.qt.io/official_releases/qt-installer-framework/3.0.1/QtInstallerFramework-win-x86.exe
|
||||||
|
- 7z x QtInstallerFramework-win-x86.exe -otools -aoa
|
||||||
|
- set PATH=%BUILD%\tools\bin;%PATH%
|
||||||
|
- binarycreator.exe -f -c installer\config\config.xml -p installer\packages nheko-installer.exe
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
description: "Development builds"
|
||||||
|
provider: GitHub
|
||||||
|
auth_token:
|
||||||
|
secure: YqB7hcM+4482eSHhtVR7ZA7N7lE78y8BC897/7UDTBQd+NWdWFW/6S+oKDie9TT7
|
||||||
|
artifact: nheko-installer.exe
|
||||||
|
force_update: true
|
||||||
|
prerelease: true
|
||||||
|
on:
|
||||||
|
appveyor_repo_tag: true
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: nheko_win_64.zip
|
- path: nheko_win_64.zip
|
||||||
- path: NhekoRelease\nheko.exe
|
- path: nheko-installer.exe
|
||||||
- path: nheko_setup.exe
|
|
||||||
|
36
cmake/MacOSXBundleInfo.plist.in
Normal file
36
cmake/MacOSXBundleInfo.plist.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleLongVersionString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>LSRequiresCarbon</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
76
cmake/QtCommon.cmake
Normal file
76
cmake/QtCommon.cmake
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
macro(fix_project_version)
|
||||||
|
if (NOT PROJECT_VERSION_PATCH)
|
||||||
|
set(PROJECT_VERSION_PATCH 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT PROJECT_VERSION_TWEAK)
|
||||||
|
set(PROJECT_VERSION_TWEAK 0)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(add_project_meta FILES_TO_INCLUDE)
|
||||||
|
if (NOT RESOURCE_FOLDER)
|
||||||
|
set(RESOURCE_FOLDER resources)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT ICON_NAME)
|
||||||
|
set(ICON_NAME nheko)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set(ICON_FILE ${RESOURCE_FOLDER}/${ICON_NAME}.icns)
|
||||||
|
elseif (WIN32)
|
||||||
|
set(ICON_FILE ${RESOURCE_FOLDER}/${ICON_NAME}.ico)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
configure_file("${PROJECT_SOURCE_DIR}/cmake/windows_metafile.rc.in"
|
||||||
|
"windows_metafile.rc"
|
||||||
|
)
|
||||||
|
set(RES_FILES "windows_metafile.rc")
|
||||||
|
set(CMAKE_RC_COMPILER_INIT windres)
|
||||||
|
ENABLE_LANGUAGE(RC)
|
||||||
|
SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set_source_files_properties(${ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||||
|
|
||||||
|
# Identify MacOS bundle
|
||||||
|
set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME})
|
||||||
|
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
|
||||||
|
set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION})
|
||||||
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
set(MACOSX_BUNDLE_COPYRIGHT ${COPYRIGHT})
|
||||||
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER ${IDENTIFIER})
|
||||||
|
set(MACOSX_BUNDLE_ICON_FILE ${ICON_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
set(${FILES_TO_INCLUDE} ${ICON_FILE})
|
||||||
|
elseif (WIN32)
|
||||||
|
set(${FILES_TO_INCLUDE} ${RES_FILES})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(init_os_bundle)
|
||||||
|
if (APPLE)
|
||||||
|
set(OS_BUNDLE MACOSX_BUNDLE)
|
||||||
|
elseif (WIN32)
|
||||||
|
IF(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
set(OS_BUNDLE WIN32)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(fix_win_compiler)
|
||||||
|
if (MSVC)
|
||||||
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
|
WIN32_EXECUTABLE YES
|
||||||
|
LINK_FLAGS "/ENTRY:mainCRTStartup"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
init_os_bundle()
|
||||||
|
fix_win_compiler()
|
28
cmake/windows_metafile.rc.in
Normal file
28
cmake/windows_metafile.rc.in
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "winver.h"
|
||||||
|
|
||||||
|
IDI_ICON1 ICON DISCARDABLE "@ICON_FILE@"
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK@
|
||||||
|
PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK@
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
FILEOS 0x00040004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000004b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "@COMPANY@"
|
||||||
|
VALUE "FileDescription", "@PROJECT_NAME@"
|
||||||
|
VALUE "FileVersion", "@PROJECT_VERSION@"
|
||||||
|
VALUE "LegalCopyright", "@COPYRIGHT@"
|
||||||
|
VALUE "InternalName", "@PROJECT_NAME@"
|
||||||
|
VALUE "OriginalFilename", "@PROJECT_NAME@.exe"
|
||||||
|
VALUE "ProductName", "@PROJECT_NAME@"
|
||||||
|
VALUE "ProductVersion", "@PROJECT_VERSION@"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
END
|
28
deploy/installer/cleanup/installscript.qs
Normal file
28
deploy/installer/cleanup/installscript.qs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function Component()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.prototype.createOperations = function()
|
||||||
|
{
|
||||||
|
component.createOperations();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( installer.value("os") === "win" )
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Cleanup AppData and registry
|
||||||
|
*/
|
||||||
|
component.addElevatedOperation("Execute","UNDOEXECUTE","cmd /C reg delete HKEY_CURRENT_USER\Software\nheko\nheko /f");
|
||||||
|
var localappdata = installer.environmentVariable("LOCALAPPDATA");
|
||||||
|
if( localappdata != "" )
|
||||||
|
{
|
||||||
|
component.addElevatedOperation("Execute","UNDOEXECUTE","cmd /C rmdir "+localappdata+"\nheko /f");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( e )
|
||||||
|
{
|
||||||
|
print( e );
|
||||||
|
}
|
||||||
|
}
|
10
deploy/installer/cleanup/package.xml
Normal file
10
deploy/installer/cleanup/package.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Package>
|
||||||
|
<DisplayName>Cleanup AppData and Registry</DisplayName>
|
||||||
|
<Description>Cleans up AppData and Registry when selected (logs you out) - Broken</Description>
|
||||||
|
<Version>__VERSION__</Version>
|
||||||
|
<ReleaseDate>__DATE__</ReleaseDate>
|
||||||
|
<SortingPriority>80</SortingPriority>
|
||||||
|
<Script>installscript.qs</Script>
|
||||||
|
<Checkable>false</Checkable>
|
||||||
|
</Package>
|
15
deploy/installer/config.xml
Normal file
15
deploy/installer/config.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Installer>
|
||||||
|
<Name>Nheko</Name>
|
||||||
|
<Version>__VERSION__</Version>
|
||||||
|
<Title>Nheko Installer</Title>
|
||||||
|
<Publisher>Mujx</Publisher>
|
||||||
|
<ProductUrl>https://github.com/mujx/nheko</ProductUrl>
|
||||||
|
<InstallerWindowIcon>nheko</InstallerWindowIcon>
|
||||||
|
<InstallerApplicationIcon>nheko</InstallerApplicationIcon>
|
||||||
|
<Logo>nheko.png</Logo>
|
||||||
|
<StartMenuDir>Nheko</StartMenuDir>
|
||||||
|
<TargetDir>@ApplicationsDir@/nheko</TargetDir>
|
||||||
|
<RunProgram>@TargetDir@/nheko.exe</RunProgram>
|
||||||
|
<ControlScript>controlscript.qs</ControlScript>
|
||||||
|
</Installer>
|
25
deploy/installer/controlscript.qs
Normal file
25
deploy/installer/controlscript.qs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Source: http://stackoverflow.com/questions/21389105/qt-installer-framework-offline-update-how
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Controller()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.prototype.TargetDirectoryPageCallback = function()
|
||||||
|
{
|
||||||
|
var widget = gui.currentPageWidget();
|
||||||
|
widget.TargetDirectoryLineEdit.textChanged.connect( this, Controller.prototype.targetChanged );
|
||||||
|
Controller.prototype.targetChanged( widget.TargetDirectoryLineEdit.text );
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.prototype.targetChanged = function( text )
|
||||||
|
{
|
||||||
|
if( text != "" && installer.fileExists(text + "/components.xml") )
|
||||||
|
{
|
||||||
|
if( QMessageBox.question("PreviousInstallation", "Previous installation detected", "Do you want to uninstall the previous installation?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes )
|
||||||
|
{
|
||||||
|
installer.execute( text+"/maintenancetool.exe", new Array("--script", text+"/uninstall.qs") )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
deploy/installer/gui/installscript.qs
Normal file
32
deploy/installer/gui/installscript.qs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
function Component()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.prototype.createOperations = function()
|
||||||
|
{
|
||||||
|
component.createOperations();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( installer.value("os") === "win" )
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Start Menu Shortcut
|
||||||
|
*/
|
||||||
|
component.addOperation( "CreateShortcut", "@TargetDir@\\nheko.exe", "@StartMenuDir@\\nheko.lnk",
|
||||||
|
"workingDirectory=@TargetDir@", "iconPath=@TargetDir@\\nheko.exe",
|
||||||
|
"iconId=0", "description=Desktop client for the Matrix protocol");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Desktop Shortcut
|
||||||
|
*/
|
||||||
|
component.addOperation( "CreateShortcut", "@TargetDir@\\nheko.exe", "@DesktopDir@\\nheko.lnk",
|
||||||
|
"workingDirectory=@TargetDir@", "iconPath=@TargetDir@\\nheko.exe",
|
||||||
|
"iconId=0", "description=Desktop client for the Matrix protocol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( e )
|
||||||
|
{
|
||||||
|
print( e );
|
||||||
|
}
|
||||||
|
}
|
14
deploy/installer/gui/package.xml
Normal file
14
deploy/installer/gui/package.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Package>
|
||||||
|
<DisplayName>Nheko</DisplayName>
|
||||||
|
<Description>Desktop client for the Matrix protocol</Description>
|
||||||
|
<Version>__VERSION__</Version>
|
||||||
|
<ReleaseDate>__DATE__</ReleaseDate>
|
||||||
|
<Licenses>
|
||||||
|
<License name="Nheko License - GPLv3" file="license.txt" />
|
||||||
|
</Licenses>
|
||||||
|
<Default>true</Default>
|
||||||
|
<ForcedInstallation>true</ForcedInstallation>
|
||||||
|
<SortingPriority>100</SortingPriority>
|
||||||
|
<Script>installscript.qs</Script>
|
||||||
|
</Package>
|
18
deploy/installer/uninstall.qs
Normal file
18
deploy/installer/uninstall.qs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
function Controller()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.prototype.IntroductionPageCallback = function()
|
||||||
|
{
|
||||||
|
gui.clickButton( buttons.NextButton );
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.prototype.ReadyForInstallationPageCallback = function()
|
||||||
|
{
|
||||||
|
gui.clickButton( buttons.CommitButton );
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.prototype.FinishedPageCallback = function()
|
||||||
|
{
|
||||||
|
gui.clickButton( buttons.FinishButton );
|
||||||
|
}
|
33
dist/MacOS/nheko.app/Contents/Info.plist
vendored
33
dist/MacOS/nheko.app/Contents/Info.plist
vendored
@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
|
|
||||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDisplayName</key>
|
|
||||||
<string>Nheko</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>nheko</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>nheko</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>Nheko</string>
|
|
||||||
<key>CFBundleIconFile</key>
|
|
||||||
<string>nheko.icns</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>0.1.0</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>0.1.0</string>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>APPL</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>NSHighResolutionCapable</key>
|
|
||||||
<true />
|
|
||||||
<key>NSMainNibFile</key>
|
|
||||||
<string></string>
|
|
||||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
|
||||||
<true />
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
BIN
dist/MacOS/nheko.app/Contents/Resources/nheko.icns
vendored
BIN
dist/MacOS/nheko.app/Contents/Resources/nheko.icns
vendored
Binary file not shown.
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
@ -49,6 +50,7 @@ class LeftRoom;
|
|||||||
|
|
||||||
constexpr int CONSENSUS_TIMEOUT = 1000;
|
constexpr int CONSENSUS_TIMEOUT = 1000;
|
||||||
constexpr int SHOW_CONTENT_TIMEOUT = 3000;
|
constexpr int SHOW_CONTENT_TIMEOUT = 3000;
|
||||||
|
constexpr int TYPING_REFRESH_TIMEOUT = 10000;
|
||||||
|
|
||||||
class ChatPage : public QWidget
|
class ChatPage : public QWidget
|
||||||
{
|
{
|
||||||
@ -69,6 +71,7 @@ signals:
|
|||||||
void unreadMessages(int count);
|
void unreadMessages(int count);
|
||||||
void showNotification(const QString &msg);
|
void showNotification(const QString &msg);
|
||||||
void showLoginPage(const QString &msg);
|
void showLoginPage(const QString &msg);
|
||||||
|
void showUserSettingsPage();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void showUnreadMessageNotification(int count);
|
void showUnreadMessageNotification(int count);
|
||||||
@ -119,10 +122,8 @@ private:
|
|||||||
QWidget *sideBarTopWidget_;
|
QWidget *sideBarTopWidget_;
|
||||||
QVBoxLayout *sideBarTopWidgetLayout_;
|
QVBoxLayout *sideBarTopWidgetLayout_;
|
||||||
|
|
||||||
QWidget *content_;
|
QFrame *content_;
|
||||||
QVBoxLayout *contentLayout_;
|
QVBoxLayout *contentLayout_;
|
||||||
QHBoxLayout *topBarLayout_;
|
|
||||||
QVBoxLayout *mainContentLayout_;
|
|
||||||
|
|
||||||
CommunitiesList *communitiesList_;
|
CommunitiesList *communitiesList_;
|
||||||
RoomList *room_list_;
|
RoomList *room_list_;
|
||||||
@ -153,6 +154,7 @@ private:
|
|||||||
|
|
||||||
// Keeps track of the users currently typing on each room.
|
// Keeps track of the users currently typing on each room.
|
||||||
QMap<QString, QList<QString>> typingUsers_;
|
QMap<QString, QList<QString>> typingUsers_;
|
||||||
|
QTimer *typingRefresher_;
|
||||||
|
|
||||||
QSharedPointer<QuickSwitcher> quickSwitcher_;
|
QSharedPointer<QuickSwitcher> quickSwitcher_;
|
||||||
QSharedPointer<OverlayModal> quickSwitcherModal_;
|
QSharedPointer<OverlayModal> quickSwitcherModal_;
|
||||||
|
@ -30,6 +30,8 @@ class OverlayModal;
|
|||||||
class RegisterPage;
|
class RegisterPage;
|
||||||
class SnackBar;
|
class SnackBar;
|
||||||
class TrayIcon;
|
class TrayIcon;
|
||||||
|
class UserSettingsPage;
|
||||||
|
class UserSettings;
|
||||||
class WelcomePage;
|
class WelcomePage;
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
@ -59,6 +61,7 @@ private slots:
|
|||||||
|
|
||||||
// Show the register page in the main window.
|
// Show the register page in the main window.
|
||||||
void showRegisterPage();
|
void showRegisterPage();
|
||||||
|
void showUserSettingsPage();
|
||||||
|
|
||||||
// Show the chat page and start communicating with the given access token.
|
// Show the chat page and start communicating with the given access token.
|
||||||
void showChatPage(QString user_id, QString home_server, QString token);
|
void showChatPage(QString user_id, QString home_server, QString token);
|
||||||
@ -85,6 +88,8 @@ private:
|
|||||||
|
|
||||||
// The main chat area.
|
// The main chat area.
|
||||||
ChatPage *chat_page_;
|
ChatPage *chat_page_;
|
||||||
|
UserSettingsPage *userSettingsPage_;
|
||||||
|
QSharedPointer<UserSettings> userSettings_;
|
||||||
|
|
||||||
// Used to hide undefined states between page transitions.
|
// Used to hide undefined states between page transitions.
|
||||||
QSharedPointer<OverlayModal> progressModal_;
|
QSharedPointer<OverlayModal> progressModal_;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
#include "MessageEvent.h"
|
#include "MessageEvent.h"
|
||||||
|
|
||||||
@ -40,8 +41,10 @@ public:
|
|||||||
void initialSync() noexcept;
|
void initialSync() noexcept;
|
||||||
void sync() noexcept;
|
void sync() noexcept;
|
||||||
void sendRoomMessage(matrix::events::MessageEventType ty,
|
void sendRoomMessage(matrix::events::MessageEventType ty,
|
||||||
|
int txnId,
|
||||||
const QString &roomid,
|
const QString &roomid,
|
||||||
const QString &msg,
|
const QString &msg,
|
||||||
|
const QFileInfo &fileinfo,
|
||||||
const QString &url = "") noexcept;
|
const QString &url = "") noexcept;
|
||||||
void login(const QString &username, const QString &password) noexcept;
|
void login(const QString &username, const QString &password) noexcept;
|
||||||
void registerUser(const QString &username,
|
void registerUser(const QString &username,
|
||||||
@ -59,10 +62,12 @@ public:
|
|||||||
void uploadImage(const QString &roomid, const QString &filename);
|
void uploadImage(const QString &roomid, const QString &filename);
|
||||||
void joinRoom(const QString &roomIdOrAlias);
|
void joinRoom(const QString &roomIdOrAlias);
|
||||||
void leaveRoom(const QString &roomId);
|
void leaveRoom(const QString &roomId);
|
||||||
|
void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
|
||||||
|
void removeTypingNotification(const QString &roomid);
|
||||||
|
|
||||||
QUrl getHomeServer() { return server_; };
|
QUrl getHomeServer() { return server_; };
|
||||||
int transactionId() { return txn_id_; };
|
int transactionId() { return txn_id_; };
|
||||||
void incrementTransactionId() { txn_id_ += 1; };
|
int incrementTransactionId() { return ++txn_id_; };
|
||||||
|
|
||||||
void reset() noexcept;
|
void reset() noexcept;
|
||||||
|
|
||||||
@ -109,6 +114,7 @@ signals:
|
|||||||
void syncFailed(const QString &msg);
|
void syncFailed(const QString &msg);
|
||||||
void joinFailed(const QString &msg);
|
void joinFailed(const QString &msg);
|
||||||
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||||
|
void messageSendFailed(const QString &roomid, const int txn_id);
|
||||||
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||||
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
||||||
void joinedRoom(const QString &room_id);
|
void joinedRoom(const QString &room_id);
|
||||||
|
@ -14,6 +14,9 @@ public:
|
|||||||
SideBarActions(QWidget *parent = nullptr);
|
SideBarActions(QWidget *parent = nullptr);
|
||||||
~SideBarActions();
|
~SideBarActions();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void showSettings();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
@ -29,18 +31,36 @@
|
|||||||
|
|
||||||
namespace msgs = matrix::events::messages;
|
namespace msgs = matrix::events::messages;
|
||||||
|
|
||||||
static const QString EMOTE_COMMAND("/me ");
|
|
||||||
static const QString JOIN_COMMAND("/join ");
|
|
||||||
|
|
||||||
class FilteredTextEdit : public QTextEdit
|
class FilteredTextEdit : public QTextEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FilteredTextEdit(QWidget *parent = nullptr);
|
explicit FilteredTextEdit(QWidget *parent = nullptr);
|
||||||
void keyPressEvent(QKeyEvent *event);
|
|
||||||
|
void stopTyping();
|
||||||
|
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
|
void submit();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void enterPressed();
|
void startedTyping();
|
||||||
|
void stoppedTyping();
|
||||||
|
void message(QString);
|
||||||
|
void command(QString name, QString args);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::deque<QString> true_history_, working_history_;
|
||||||
|
size_t history_index_;
|
||||||
|
QTimer *typingTimer_;
|
||||||
|
|
||||||
|
void textChanged();
|
||||||
|
void afterCompletion(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextInputWidget : public QFrame
|
class TextInputWidget : public QFrame
|
||||||
@ -51,8 +71,9 @@ public:
|
|||||||
TextInputWidget(QWidget *parent = 0);
|
TextInputWidget(QWidget *parent = 0);
|
||||||
~TextInputWidget();
|
~TextInputWidget();
|
||||||
|
|
||||||
|
void stopTyping();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onSendButtonClicked();
|
|
||||||
void openFileSelection();
|
void openFileSelection();
|
||||||
void hideUploadSpinner();
|
void hideUploadSpinner();
|
||||||
void focusLineEdit() { input_->setFocus(); };
|
void focusLineEdit() { input_->setFocus(); };
|
||||||
@ -66,10 +87,15 @@ signals:
|
|||||||
void uploadImage(QString filename);
|
void uploadImage(QString filename);
|
||||||
void sendJoinRoomRequest(const QString &room);
|
void sendJoinRoomRequest(const QString &room);
|
||||||
|
|
||||||
|
void startedTyping();
|
||||||
|
void stoppedTyping();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void focusInEvent(QFocusEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showUploadSpinner();
|
void showUploadSpinner();
|
||||||
QString parseEmoteCommand(const QString &cmd);
|
void command(QString name, QString args);
|
||||||
QString parseJoinCommand(const QString &cmd);
|
|
||||||
|
|
||||||
QHBoxLayout *topLayout_;
|
QHBoxLayout *topLayout_;
|
||||||
FilteredTextEdit *input_;
|
FilteredTextEdit *input_;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QQueue>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
|
||||||
#include "Emote.h"
|
#include "Emote.h"
|
||||||
@ -42,18 +43,26 @@ namespace events = matrix::events;
|
|||||||
// but not yet confirmed by the homeserver through sync.
|
// but not yet confirmed by the homeserver through sync.
|
||||||
struct PendingMessage
|
struct PendingMessage
|
||||||
{
|
{
|
||||||
|
matrix::events::MessageEventType ty;
|
||||||
int txn_id;
|
int txn_id;
|
||||||
QString body;
|
QString body;
|
||||||
|
QString filename;
|
||||||
QString event_id;
|
QString event_id;
|
||||||
TimelineItem *widget;
|
TimelineItem *widget;
|
||||||
|
|
||||||
PendingMessage(int txn_id, QString body, QString event_id, TimelineItem *widget)
|
PendingMessage(matrix::events::MessageEventType ty,
|
||||||
: txn_id(txn_id)
|
int txn_id,
|
||||||
|
QString body,
|
||||||
|
QString filename,
|
||||||
|
QString event_id,
|
||||||
|
TimelineItem *widget)
|
||||||
|
: ty(ty)
|
||||||
|
, txn_id(txn_id)
|
||||||
, body(body)
|
, body(body)
|
||||||
|
, filename(filename)
|
||||||
, event_id(event_id)
|
, event_id(event_id)
|
||||||
, widget(widget)
|
, widget(widget)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// In which place new TimelineItems should be inserted.
|
// In which place new TimelineItems should be inserted.
|
||||||
@ -87,8 +96,8 @@ public:
|
|||||||
|
|
||||||
// Add new events at the end of the timeline.
|
// Add new events at the end of the timeline.
|
||||||
int addEvents(const Timeline &timeline);
|
int addEvents(const Timeline &timeline);
|
||||||
void addUserMessage(matrix::events::MessageEventType ty, const QString &msg, int txn_id);
|
void addUserMessage(matrix::events::MessageEventType ty, const QString &msg);
|
||||||
void addUserMessage(const QString &url, const QString &filename, int txn_id);
|
void addUserMessage(const QString &url, const QString &filename);
|
||||||
void updatePendingMessage(int txn_id, QString event_id);
|
void updatePendingMessage(int txn_id, QString event_id);
|
||||||
void scrollDown();
|
void scrollDown();
|
||||||
|
|
||||||
@ -103,6 +112,11 @@ public slots:
|
|||||||
// Whether or not the initial batch has been loaded.
|
// Whether or not the initial batch has been loaded.
|
||||||
bool hasLoaded() { return scroll_layout_->count() > 1 || isTimelineFinished; };
|
bool hasLoaded() { return scroll_layout_->count() > 1 || isTimelineFinished; };
|
||||||
|
|
||||||
|
void handleFailedMessage(int txnid);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void sendNextPendingMessage();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updateLastTimelineMessage(const QString &user, const DescInfo &info);
|
void updateLastTimelineMessage(const QString &user, const DescInfo &info);
|
||||||
|
|
||||||
@ -116,13 +130,11 @@ private:
|
|||||||
// sender's name.
|
// sender's name.
|
||||||
bool isSenderRendered(const QString &user_id, TimelineDirection direction);
|
bool isSenderRendered(const QString &user_id, TimelineDirection direction);
|
||||||
|
|
||||||
bool isPendingMessage(const QString &eventid,
|
bool isPendingMessage(const QString &txnid, const QString &sender, const QString &userid);
|
||||||
const QString &body,
|
void removePendingMessage(const QString &txnid);
|
||||||
const QString &sender,
|
|
||||||
const QString &userid);
|
|
||||||
void removePendingMessage(const QString &eventid, const QString &body);
|
|
||||||
|
|
||||||
bool isDuplicate(const QString &event_id) { return eventIds_.contains(event_id); };
|
bool isDuplicate(const QString &event_id) { return eventIds_.contains(event_id); };
|
||||||
|
void handleNewUserMessage(PendingMessage msg);
|
||||||
|
|
||||||
// Return nullptr if the event couldn't be parsed.
|
// Return nullptr if the event couldn't be parsed.
|
||||||
TimelineItem *parseMessageEvent(const QJsonObject &event, TimelineDirection direction);
|
TimelineItem *parseMessageEvent(const QJsonObject &event, TimelineDirection direction);
|
||||||
@ -163,6 +175,7 @@ private:
|
|||||||
|
|
||||||
// The events currently rendered. Used for duplicate detection.
|
// The events currently rendered. Used for duplicate detection.
|
||||||
QMap<QString, bool> eventIds_;
|
QMap<QString, bool> eventIds_;
|
||||||
QList<PendingMessage> pending_msgs_;
|
QQueue<PendingMessage> pending_msgs_;
|
||||||
|
QList<PendingMessage> pending_sent_msgs_;
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
|
|
||||||
|
#include "MessageEvent.h"
|
||||||
|
|
||||||
class JoinedRoom;
|
class JoinedRoom;
|
||||||
class MatrixClient;
|
class MatrixClient;
|
||||||
class RoomInfoListItem;
|
class RoomInfoListItem;
|
||||||
@ -61,12 +63,13 @@ signals:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setHistoryView(const QString &room_id);
|
void setHistoryView(const QString &room_id);
|
||||||
void sendTextMessage(const QString &msg);
|
void queueTextMessage(const QString &msg);
|
||||||
void sendEmoteMessage(const QString &msg);
|
void queueEmoteMessage(const QString &msg);
|
||||||
void sendImageMessage(const QString &roomid, const QString &filename, const QString &url);
|
void queueImageMessage(const QString &roomid, const QString &filename, const QString &url);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void messageSent(const QString &eventid, const QString &roomid, int txnid);
|
void messageSent(const QString &eventid, const QString &roomid, int txnid);
|
||||||
|
void messageSendFailed(const QString &roomid, int txnid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString active_room_;
|
QString active_room_;
|
||||||
|
86
include/UserSettingsPage.h
Normal file
86
include/UserSettingsPage.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class Toggle;
|
||||||
|
|
||||||
|
constexpr int OptionMargin = 6;
|
||||||
|
constexpr int LayoutTopMargin = 50;
|
||||||
|
constexpr int LayoutBottomMargin = LayoutTopMargin;
|
||||||
|
|
||||||
|
class UserSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UserSettings();
|
||||||
|
|
||||||
|
void save();
|
||||||
|
void load();
|
||||||
|
void setTheme(QString theme) { theme_ = theme; }
|
||||||
|
void setTray(bool state) { isTrayEnabled_ = state; }
|
||||||
|
|
||||||
|
QString theme() const { return !theme_.isEmpty() ? theme_ : "default"; }
|
||||||
|
bool isTrayEnabled() const { return isTrayEnabled_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString theme_;
|
||||||
|
bool isTrayEnabled_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HorizontalLine : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HorizontalLine(QWidget *parent = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
class UserSettingsPage : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void moveBack();
|
||||||
|
void trayOptionChanged(bool value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Layouts
|
||||||
|
QVBoxLayout *topLayout_;
|
||||||
|
QVBoxLayout *mainLayout_;
|
||||||
|
QHBoxLayout *topBarLayout_;
|
||||||
|
|
||||||
|
// Shared settings object.
|
||||||
|
QSharedPointer<UserSettings> settings_;
|
||||||
|
|
||||||
|
Toggle *trayToggle_;
|
||||||
|
QComboBox *themeCombo_;
|
||||||
|
|
||||||
|
int sideMargin_ = 0;
|
||||||
|
};
|
@ -60,12 +60,31 @@ isMessageEvent(EventType type);
|
|||||||
bool
|
bool
|
||||||
isStateEvent(EventType type);
|
isStateEvent(EventType type);
|
||||||
|
|
||||||
|
class UnsignedData
|
||||||
|
: public Deserializable
|
||||||
|
, public Serializable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double age() const { return age_; }
|
||||||
|
QString transactionId() const { return transaction_id_; }
|
||||||
|
|
||||||
|
bool isEmpty() const { return age_ <= 0 && transaction_id_.isEmpty(); }
|
||||||
|
|
||||||
|
void deserialize(const QJsonValue &data) override;
|
||||||
|
QJsonObject serialize() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double age_ = 0;
|
||||||
|
QString transaction_id_;
|
||||||
|
};
|
||||||
|
|
||||||
template<class Content>
|
template<class Content>
|
||||||
class Event : public Deserializable, public Serializable
|
class Event : public Deserializable, public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Content content() const;
|
Content content() const;
|
||||||
EventType eventType() const;
|
EventType eventType() const;
|
||||||
|
UnsignedData unsignedData() const { return unsignedData_; }
|
||||||
|
|
||||||
void deserialize(const QJsonValue &data) override;
|
void deserialize(const QJsonValue &data) override;
|
||||||
QJsonObject serialize() const override;
|
QJsonObject serialize() const override;
|
||||||
@ -73,6 +92,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Content content_;
|
Content content_;
|
||||||
EventType type_;
|
EventType type_;
|
||||||
|
UnsignedData unsignedData_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Content>
|
template<class Content>
|
||||||
@ -100,6 +120,9 @@ Event<Content>::deserialize(const QJsonValue &data)
|
|||||||
|
|
||||||
content_.deserialize(object.value("content"));
|
content_.deserialize(object.value("content"));
|
||||||
type_ = extractEventType(object);
|
type_ = extractEventType(object);
|
||||||
|
|
||||||
|
if (object.contains("unsigned"))
|
||||||
|
unsignedData_.deserialize(object.value("unsigned"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Content>
|
template<class Content>
|
||||||
@ -149,6 +172,9 @@ Event<Content>::serialize() const
|
|||||||
|
|
||||||
object["content"] = content_.serialize();
|
object["content"] = content_.serialize();
|
||||||
|
|
||||||
|
if (!unsignedData_.isEmpty())
|
||||||
|
object["unsigned"] = unsignedData_.serialize();
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
} // namespace events
|
} // namespace events
|
||||||
|
@ -12,8 +12,7 @@ enum class AvatarType
|
|||||||
Letter
|
Letter
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace sidebar
|
namespace sidebar {
|
||||||
{
|
|
||||||
static const int SmallSize = 60;
|
static const int SmallSize = 60;
|
||||||
static const int NormalSize = 300;
|
static const int NormalSize = 300;
|
||||||
static const int CommunitiesSidebarSize = 64;
|
static const int CommunitiesSidebarSize = 64;
|
||||||
|
110
include/ui/ToggleButton.h
Normal file
110
include/ui/ToggleButton.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractButton>
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
class ToggleTrack;
|
||||||
|
class ToggleThumb;
|
||||||
|
|
||||||
|
enum class Position
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
};
|
||||||
|
|
||||||
|
class Toggle : public QAbstractButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
|
||||||
|
Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
|
||||||
|
Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
|
||||||
|
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||||
|
|
||||||
|
public:
|
||||||
|
Toggle(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void setState(bool isEnabled);
|
||||||
|
|
||||||
|
void setActiveColor(const QColor &color);
|
||||||
|
void setDisabledColor(const QColor &color);
|
||||||
|
void setInactiveColor(const QColor &color);
|
||||||
|
void setTrackColor(const QColor &color);
|
||||||
|
|
||||||
|
QColor activeColor() const { return activeColor_; };
|
||||||
|
QColor disabledColor() const { return disabledColor_; };
|
||||||
|
QColor inactiveColor() const { return inactiveColor_; };
|
||||||
|
QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
|
||||||
|
|
||||||
|
QSize sizeHint() const override { return QSize(64, 48); };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void setupProperties();
|
||||||
|
|
||||||
|
ToggleTrack *track_;
|
||||||
|
ToggleThumb *thumb_;
|
||||||
|
|
||||||
|
QColor disabledColor_;
|
||||||
|
QColor activeColor_;
|
||||||
|
QColor inactiveColor_;
|
||||||
|
QColor trackColor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ToggleThumb : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ToggleThumb(Toggle *parent);
|
||||||
|
|
||||||
|
Position shift() const { return position_; };
|
||||||
|
qreal offset() const { return offset_; };
|
||||||
|
QColor thumbColor() const { return thumbColor_; };
|
||||||
|
|
||||||
|
void setShift(Position position);
|
||||||
|
void setThumbColor(const QColor &color)
|
||||||
|
{
|
||||||
|
thumbColor_ = color;
|
||||||
|
update();
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateOffset();
|
||||||
|
|
||||||
|
Toggle *const toggle_;
|
||||||
|
QColor thumbColor_;
|
||||||
|
|
||||||
|
Position position_;
|
||||||
|
qreal offset_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ToggleTrack : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ToggleTrack(Toggle *parent);
|
||||||
|
|
||||||
|
void setTrackColor(const QColor &color);
|
||||||
|
QColor trackColor() const { return trackColor_; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Toggle *const toggle_;
|
||||||
|
QColor trackColor_;
|
||||||
|
};
|
10
src/Cache.cc
10
src/Cache.cc
@ -31,11 +31,11 @@ static const lmdb::val NEXT_BATCH_KEY("next_batch");
|
|||||||
static const lmdb::val transactionID("transaction_id");
|
static const lmdb::val transactionID("transaction_id");
|
||||||
|
|
||||||
Cache::Cache(const QString &userId)
|
Cache::Cache(const QString &userId)
|
||||||
: env_{ nullptr }
|
: env_{nullptr}
|
||||||
, stateDb_{ 0 }
|
, stateDb_{0}
|
||||||
, roomDb_{ 0 }
|
, roomDb_{0}
|
||||||
, isMounted_{ false }
|
, isMounted_{false}
|
||||||
, userId_{ userId }
|
, userId_{userId}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -72,8 +72,8 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
topLayout_->addWidget(splitter);
|
topLayout_->addWidget(splitter);
|
||||||
|
|
||||||
// SideBar
|
// SideBar
|
||||||
sideBar_ = new QWidget(this);
|
sideBar_ = new QFrame(this);
|
||||||
sideBar_->setMinimumSize(QSize(ui::sidebar::NormalSize, 0));
|
sideBar_->setMinimumSize(QSize(ui::sidebar::NormalSize, parent->height()));
|
||||||
sideBarLayout_ = new QVBoxLayout(sideBar_);
|
sideBarLayout_ = new QVBoxLayout(sideBar_);
|
||||||
sideBarLayout_->setSpacing(0);
|
sideBarLayout_->setSpacing(0);
|
||||||
sideBarLayout_->setMargin(0);
|
sideBarLayout_->setMargin(0);
|
||||||
@ -93,40 +93,33 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
|
|
||||||
sideBarTopWidget_ = new QWidget(sideBar_);
|
sideBarTopWidget_ = new QWidget(sideBar_);
|
||||||
sideBarTopWidget_->setStyleSheet("background-color: #d6dde3; color: #ebebeb;");
|
sideBarTopWidget_->setStyleSheet("background-color: #d6dde3; color: #ebebeb;");
|
||||||
|
sidebarActions_ = new SideBarActions(this);
|
||||||
|
connect(
|
||||||
|
sidebarActions_, &SideBarActions::showSettings, this, &ChatPage::showUserSettingsPage);
|
||||||
|
|
||||||
sideBarTopLayout_->addWidget(sideBarTopWidget_);
|
user_info_widget_ = new UserInfoWidget(sideBar_);
|
||||||
|
room_list_ = new RoomList(client, sideBar_);
|
||||||
|
|
||||||
sideBarTopWidgetLayout_ = new QVBoxLayout(sideBarTopWidget_);
|
sideBarLayout_->addWidget(user_info_widget_);
|
||||||
sideBarTopWidgetLayout_->setSpacing(0);
|
sideBarLayout_->addWidget(room_list_);
|
||||||
sideBarTopWidgetLayout_->setMargin(0);
|
sideBarLayout_->addWidget(sidebarActions_);
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
content_ = new QWidget(this);
|
content_ = new QFrame(this);
|
||||||
contentLayout_ = new QVBoxLayout(content_);
|
contentLayout_ = new QVBoxLayout(content_);
|
||||||
contentLayout_->setSpacing(0);
|
contentLayout_->setSpacing(0);
|
||||||
contentLayout_->setMargin(0);
|
contentLayout_->setMargin(0);
|
||||||
|
|
||||||
topBarLayout_ = new QHBoxLayout();
|
top_bar_ = new TopRoomBar(this);
|
||||||
topBarLayout_->setSpacing(0);
|
view_manager_ = new TimelineViewManager(client, this);
|
||||||
mainContentLayout_ = new QVBoxLayout();
|
|
||||||
mainContentLayout_->setSpacing(0);
|
|
||||||
mainContentLayout_->setMargin(0);
|
|
||||||
|
|
||||||
contentLayout_->addLayout(topBarLayout_);
|
contentLayout_->addWidget(top_bar_);
|
||||||
contentLayout_->addLayout(mainContentLayout_);
|
contentLayout_->addWidget(view_manager_);
|
||||||
|
|
||||||
// Splitter
|
// Splitter
|
||||||
splitter->addWidget(sideBar_);
|
splitter->addWidget(sideBar_);
|
||||||
splitter->addWidget(content_);
|
splitter->addWidget(content_);
|
||||||
|
splitter->setSizes({ui::sidebar::NormalSize, parent->width() - ui::sidebar::NormalSize});
|
||||||
room_list_ = new RoomList(client, sideBar_);
|
|
||||||
sideBarMainLayout_->addWidget(room_list_);
|
|
||||||
|
|
||||||
top_bar_ = new TopRoomBar(this);
|
|
||||||
topBarLayout_->addWidget(top_bar_);
|
|
||||||
|
|
||||||
view_manager_ = new TimelineViewManager(client, this);
|
|
||||||
mainContentLayout_->addWidget(view_manager_);
|
|
||||||
|
|
||||||
text_input_ = new TextInputWidget(this);
|
text_input_ = new TextInputWidget(this);
|
||||||
typingDisplay_ = new TypingDisplay(this);
|
typingDisplay_ = new TypingDisplay(this);
|
||||||
@ -135,6 +128,8 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
|
|
||||||
user_info_widget_ = new UserInfoWidget(sideBarTopWidget_);
|
user_info_widget_ = new UserInfoWidget(sideBarTopWidget_);
|
||||||
sideBarTopWidgetLayout_->addWidget(user_info_widget_);
|
sideBarTopWidgetLayout_->addWidget(user_info_widget_);
|
||||||
|
typingRefresher_ = new QTimer(this);
|
||||||
|
typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT);
|
||||||
|
|
||||||
connect(user_info_widget_, SIGNAL(logout()), client_.data(), SLOT(logout()));
|
connect(user_info_widget_, SIGNAL(logout()), client_.data(), SLOT(logout()));
|
||||||
connect(client_.data(), SIGNAL(loggedOut()), this, SLOT(logout()));
|
connect(client_.data(), SIGNAL(loggedOut()), this, SLOT(logout()));
|
||||||
@ -150,6 +145,7 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
|
|
||||||
typingDisplay_->setUsers(users);
|
typingDisplay_->setUsers(users);
|
||||||
});
|
});
|
||||||
|
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::stopTyping);
|
||||||
|
|
||||||
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
||||||
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
||||||
@ -170,6 +166,20 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
room_list_->updateUnreadMessageCount(roomid, count);
|
room_list_->updateUnreadMessageCount(roomid, count);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(text_input_, &TextInputWidget::startedTyping, this, [=]() {
|
||||||
|
typingRefresher_->start();
|
||||||
|
client_->sendTypingNotification(current_room_);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(text_input_, &TextInputWidget::stoppedTyping, this, [=]() {
|
||||||
|
typingRefresher_->stop();
|
||||||
|
client_->removeTypingNotification(current_room_);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(typingRefresher_, &QTimer::timeout, this, [=]() {
|
||||||
|
client_->sendTypingNotification(current_room_);
|
||||||
|
});
|
||||||
|
|
||||||
connect(view_manager_,
|
connect(view_manager_,
|
||||||
&TimelineViewManager::updateRoomsLastMessage,
|
&TimelineViewManager::updateRoomsLastMessage,
|
||||||
room_list_,
|
room_list_,
|
||||||
@ -183,12 +193,12 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
connect(text_input_,
|
connect(text_input_,
|
||||||
SIGNAL(sendTextMessage(const QString &)),
|
SIGNAL(sendTextMessage(const QString &)),
|
||||||
view_manager_,
|
view_manager_,
|
||||||
SLOT(sendTextMessage(const QString &)));
|
SLOT(queueTextMessage(const QString &)));
|
||||||
|
|
||||||
connect(text_input_,
|
connect(text_input_,
|
||||||
SIGNAL(sendEmoteMessage(const QString &)),
|
SIGNAL(sendEmoteMessage(const QString &)),
|
||||||
view_manager_,
|
view_manager_,
|
||||||
SLOT(sendEmoteMessage(const QString &)));
|
SLOT(queueEmoteMessage(const QString &)));
|
||||||
|
|
||||||
connect(text_input_,
|
connect(text_input_,
|
||||||
&TextInputWidget::sendJoinRoomRequest,
|
&TextInputWidget::sendJoinRoomRequest,
|
||||||
@ -205,7 +215,7 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
this,
|
this,
|
||||||
[=](QString roomid, QString filename, QString url) {
|
[=](QString roomid, QString filename, QString url) {
|
||||||
text_input_->hideUploadSpinner();
|
text_input_->hideUploadSpinner();
|
||||||
view_manager_->sendImageMessage(roomid, filename, url);
|
view_manager_->queueImageMessage(roomid, filename, url);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(client_.data(),
|
connect(client_.data(),
|
||||||
@ -604,6 +614,7 @@ ChatPage::showQuickSwitcher()
|
|||||||
connect(quickSwitcher_.data(), &QuickSwitcher::closing, this, [=]() {
|
connect(quickSwitcher_.data(), &QuickSwitcher::closing, this, [=]() {
|
||||||
if (!this->quickSwitcherModal_.isNull())
|
if (!this->quickSwitcherModal_.isNull())
|
||||||
this->quickSwitcherModal_->fadeOut();
|
this->quickSwitcherModal_->fadeOut();
|
||||||
|
this->text_input_->setFocus(Qt::FocusReason::PopupFocusReason);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,8 +628,12 @@ ChatPage::showQuickSwitcher()
|
|||||||
|
|
||||||
QMap<QString, QString> rooms;
|
QMap<QString, QString> rooms;
|
||||||
|
|
||||||
for (auto it = state_manager_.constBegin(); it != state_manager_.constEnd(); ++it)
|
for (auto it = state_manager_.constBegin(); it != state_manager_.constEnd(); ++it) {
|
||||||
rooms.insert(it.value().getName(), it.key());
|
QString deambiguator = it.value().canonical_alias.content().alias();
|
||||||
|
if (deambiguator == "")
|
||||||
|
deambiguator = it.key();
|
||||||
|
rooms.insert(it.value().getName() + " (" + deambiguator + ")", it.key());
|
||||||
|
}
|
||||||
|
|
||||||
quickSwitcher_->setRoomList(rooms);
|
quickSwitcher_->setRoomList(rooms);
|
||||||
quickSwitcherModal_->fadeIn();
|
quickSwitcherModal_->fadeIn();
|
||||||
@ -662,13 +677,20 @@ ChatPage::updateTypingUsers(const QString &roomid, const QList<QString> &user_id
|
|||||||
{
|
{
|
||||||
QStringList users;
|
QStringList users;
|
||||||
|
|
||||||
for (const auto uid : user_ids)
|
QSettings settings;
|
||||||
|
QString user_id = settings.value("auth/user_id").toString();
|
||||||
|
|
||||||
|
for (const auto uid : user_ids) {
|
||||||
|
if (uid == user_id)
|
||||||
|
continue;
|
||||||
users.append(TimelineViewManager::displayName(uid));
|
users.append(TimelineViewManager::displayName(uid));
|
||||||
|
}
|
||||||
|
|
||||||
users.sort();
|
users.sort();
|
||||||
|
|
||||||
if (current_room_ == roomid)
|
if (current_room_ == roomid) {
|
||||||
typingDisplay_->setUsers(users);
|
typingDisplay_->setUsers(users);
|
||||||
|
}
|
||||||
|
|
||||||
typingUsers_.insert(roomid, users);
|
typingUsers_.insert(roomid, users);
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
|
|
||||||
EmojiPanel::EmojiPanel(QWidget *parent)
|
EmojiPanel::EmojiPanel(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, shadowMargin_{ 2 }
|
, shadowMargin_{2}
|
||||||
, width_{ 370 }
|
, width_{370}
|
||||||
, height_{ 350 }
|
, height_{350}
|
||||||
, animationDuration_{ 100 }
|
, animationDuration_{100}
|
||||||
, categoryIconSize_{ 20 }
|
, categoryIconSize_{20}
|
||||||
{
|
{
|
||||||
setStyleSheet("QWidget {background: #fff; color: #e8e8e8; border: none;}"
|
setStyleSheet("QWidget {background: #fff; color: #e8e8e8; border: none;}"
|
||||||
"QScrollBar:vertical { background-color: #fff; width: 8px; margin: 0px "
|
"QScrollBar:vertical { background-color: #fff; width: 8px; margin: 0px "
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
EmojiPickButton::EmojiPickButton(QWidget *parent)
|
EmojiPickButton::EmojiPickButton(QWidget *parent)
|
||||||
: FlatButton(parent)
|
: FlatButton(parent)
|
||||||
, panel_{ nullptr }
|
, panel_{nullptr}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
2847
src/EmojiProvider.cc
2847
src/EmojiProvider.cc
File diff suppressed because it is too large
Load Diff
@ -32,8 +32,8 @@ ImageItem::ImageItem(QSharedPointer<MatrixClient> client,
|
|||||||
const events::MessageEvent<msgs::Image> &event,
|
const events::MessageEvent<msgs::Image> &event,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, event_{ event }
|
, event_{event}
|
||||||
, client_{ client }
|
, client_{client}
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setCursor(Qt::PointingHandCursor);
|
setCursor(Qt::PointingHandCursor);
|
||||||
@ -66,9 +66,9 @@ ImageItem::ImageItem(QSharedPointer<MatrixClient> client,
|
|||||||
const QString &filename,
|
const QString &filename,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, url_{ url }
|
, url_{url}
|
||||||
, text_{ QFileInfo(filename).fileName() }
|
, text_{QFileInfo(filename).fileName()}
|
||||||
, client_{ client }
|
, client_{client}
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setCursor(Qt::PointingHandCursor);
|
setCursor(Qt::PointingHandCursor);
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#include "ImageOverlayDialog.h"
|
#include "ImageOverlayDialog.h"
|
||||||
|
|
||||||
ImageOverlayDialog::ImageOverlayDialog(QPixmap image, QWidget *parent)
|
ImageOverlayDialog::ImageOverlayDialog(QPixmap image, QWidget *parent)
|
||||||
: QWidget{ parent }
|
: QWidget{parent}
|
||||||
, originalImage_{ image }
|
, originalImage_{image}
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setParent(0);
|
setParent(0);
|
||||||
|
@ -41,10 +41,10 @@ LoginRequest::serialize() noexcept
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QJsonObject body{
|
QJsonObject body{
|
||||||
{ "type", "m.login.password" },
|
{"type", "m.login.password"},
|
||||||
{ "user", user_ },
|
{"user", user_},
|
||||||
{ "password", password_ },
|
{"password", password_},
|
||||||
{ "initial_device_display_name", initialDeviceName },
|
{"initial_device_display_name", initialDeviceName},
|
||||||
};
|
};
|
||||||
|
|
||||||
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, inferredServerAddress_()
|
, inferredServerAddress_()
|
||||||
, client_{ client }
|
, client_{client}
|
||||||
{
|
{
|
||||||
setStyleSheet("background-color: #fff");
|
setStyleSheet("background-color: #fff");
|
||||||
|
|
||||||
|
@ -31,23 +31,21 @@
|
|||||||
#include "RegisterPage.h"
|
#include "RegisterPage.h"
|
||||||
#include "SnackBar.h"
|
#include "SnackBar.h"
|
||||||
#include "TrayIcon.h"
|
#include "TrayIcon.h"
|
||||||
|
#include "UserSettingsPage.h"
|
||||||
#include "WelcomePage.h"
|
#include "WelcomePage.h"
|
||||||
|
|
||||||
MainWindow *MainWindow::instance_ = nullptr;
|
MainWindow *MainWindow::instance_ = nullptr;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, progressModal_{ nullptr }
|
, progressModal_{nullptr}
|
||||||
, spinner_{ nullptr }
|
, spinner_{nullptr}
|
||||||
{
|
{
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
setSizePolicy(sizePolicy);
|
|
||||||
setWindowTitle("nheko");
|
setWindowTitle("nheko");
|
||||||
setObjectName("MainWindow");
|
setObjectName("MainWindow");
|
||||||
setStyleSheet("QWidget#MainWindow {background-color: #fff}");
|
setStyleSheet("QWidget#MainWindow {background-color: #fff}");
|
||||||
|
|
||||||
restoreWindowSize();
|
restoreWindowSize();
|
||||||
setMinimumSize(QSize(conf::window::minWidth, conf::window::minHeight));
|
|
||||||
|
|
||||||
QFont font("Open Sans");
|
QFont font("Open Sans");
|
||||||
font.setPixelSize(conf::fontSize);
|
font.setPixelSize(conf::fontSize);
|
||||||
@ -55,12 +53,14 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
setFont(font);
|
setFont(font);
|
||||||
|
|
||||||
client_ = QSharedPointer<MatrixClient>(new MatrixClient("matrix.org"));
|
client_ = QSharedPointer<MatrixClient>(new MatrixClient("matrix.org"));
|
||||||
|
userSettings_ = QSharedPointer<UserSettings>(new UserSettings);
|
||||||
trayIcon_ = new TrayIcon(":/logos/nheko-32.png", this);
|
trayIcon_ = new TrayIcon(":/logos/nheko-32.png", this);
|
||||||
|
|
||||||
welcome_page_ = new WelcomePage(this);
|
welcome_page_ = new WelcomePage(this);
|
||||||
login_page_ = new LoginPage(client_, this);
|
login_page_ = new LoginPage(client_, this);
|
||||||
register_page_ = new RegisterPage(client_, this);
|
register_page_ = new RegisterPage(client_, this);
|
||||||
chat_page_ = new ChatPage(client_, this);
|
chat_page_ = new ChatPage(client_, this);
|
||||||
|
userSettingsPage_ = new UserSettingsPage(userSettings_, this);
|
||||||
|
|
||||||
// Initialize sliding widget manager.
|
// Initialize sliding widget manager.
|
||||||
pageStack_ = new QStackedWidget(this);
|
pageStack_ = new QStackedWidget(this);
|
||||||
@ -68,6 +68,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
pageStack_->addWidget(login_page_);
|
pageStack_->addWidget(login_page_);
|
||||||
pageStack_->addWidget(register_page_);
|
pageStack_->addWidget(register_page_);
|
||||||
pageStack_->addWidget(chat_page_);
|
pageStack_->addWidget(chat_page_);
|
||||||
|
pageStack_->addWidget(userSettingsPage_);
|
||||||
|
|
||||||
setCentralWidget(pageStack_);
|
setCentralWidget(pageStack_);
|
||||||
|
|
||||||
@ -86,12 +87,21 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
showLoginPage();
|
showLoginPage();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(userSettingsPage_, &UserSettingsPage::moveBack, this, [=]() {
|
||||||
|
pageStack_->setCurrentWidget(chat_page_);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(
|
||||||
|
userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
|
||||||
|
|
||||||
connect(trayIcon_,
|
connect(trayIcon_,
|
||||||
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||||
this,
|
this,
|
||||||
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||||
|
|
||||||
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
|
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
|
||||||
|
connect(
|
||||||
|
chat_page_, &ChatPage::showUserSettingsPage, this, &MainWindow::showUserSettingsPage);
|
||||||
|
|
||||||
connect(client_.data(),
|
connect(client_.data(),
|
||||||
SIGNAL(loginSuccess(QString, QString, QString)),
|
SIGNAL(loginSuccess(QString, QString, QString)),
|
||||||
@ -101,8 +111,15 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
|
QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
|
||||||
connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
|
connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
|
||||||
|
|
||||||
|
QShortcut *quickSwitchShortcut = new QShortcut(QKeySequence("Ctrl+K"), this);
|
||||||
|
connect(quickSwitchShortcut, &QShortcut::activated, this, [=]() {
|
||||||
|
chat_page_->showQuickSwitcher();
|
||||||
|
});
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
|
trayIcon_->setVisible(userSettings_->isTrayEnabled());
|
||||||
|
|
||||||
if (hasActiveUser()) {
|
if (hasActiveUser()) {
|
||||||
QString token = settings.value("auth/access_token").toString();
|
QString token = settings.value("auth/access_token").toString();
|
||||||
QString home_server = settings.value("auth/home_server").toString();
|
QString home_server = settings.value("auth/home_server").toString();
|
||||||
@ -234,10 +251,16 @@ MainWindow::showRegisterPage()
|
|||||||
pageStack_->setCurrentWidget(register_page_);
|
pageStack_->setCurrentWidget(register_page_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MainWindow::showUserSettingsPage()
|
||||||
|
{
|
||||||
|
pageStack_->setCurrentWidget(userSettingsPage_);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWindow::closeEvent(QCloseEvent *event)
|
MainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if (isVisible()) {
|
if (isVisible() && userSettings_->isTrayEnabled()) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@
|
|||||||
|
|
||||||
MatrixClient::MatrixClient(QString server, QObject *parent)
|
MatrixClient::MatrixClient(QString server, QObject *parent)
|
||||||
: QNetworkAccessManager(parent)
|
: QNetworkAccessManager(parent)
|
||||||
, clientApiUrl_{ "/_matrix/client/r0" }
|
, clientApiUrl_{"/_matrix/client/r0"}
|
||||||
, mediaApiUrl_{ "/_matrix/media/r0" }
|
, mediaApiUrl_{"/_matrix/media/r0"}
|
||||||
, server_{ "https://" + server }
|
, server_{"https://" + server}
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
txn_id_ = settings.value("client/transaction_id", 1).toInt();
|
txn_id_ = settings.value("client/transaction_id", 1).toInt();
|
||||||
@ -119,7 +119,6 @@ MatrixClient::login(const QString &username, const QString &password) noexcept
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MatrixClient::logout() noexcept
|
MatrixClient::logout() noexcept
|
||||||
{
|
{
|
||||||
@ -260,9 +259,11 @@ MatrixClient::sync() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MatrixClient::sendRoomMessage(matrix::events::MessageEventType ty,
|
MatrixClient::sendRoomMessage(mtx::events::MessageType ty,
|
||||||
|
int txnId,
|
||||||
const QString &roomid,
|
const QString &roomid,
|
||||||
const QString &msg,
|
const QString &msg,
|
||||||
|
const QFileInfo &fileinfo,
|
||||||
const QString &url) noexcept
|
const QString &url) noexcept
|
||||||
{
|
{
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
@ -940,3 +941,53 @@ MatrixClient::leaveRoom(const QString &roomId)
|
|||||||
emit leftRoom(roomId);
|
emit leftRoom(roomId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::sendTypingNotification(const QString &roomid, int timeoutInMillis)
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
QString user_id = settings.value("auth/user_id").toString();
|
||||||
|
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("access_token", token_);
|
||||||
|
|
||||||
|
QUrl endpoint(server_);
|
||||||
|
endpoint.setPath(clientApiUrl_ + QString("/rooms/%1/typing/%2").arg(roomid).arg(user_id));
|
||||||
|
|
||||||
|
endpoint.setQuery(query);
|
||||||
|
|
||||||
|
QString msgType("");
|
||||||
|
QJsonObject body;
|
||||||
|
|
||||||
|
body = {{"typing", true}, {"timeout", timeoutInMillis}};
|
||||||
|
|
||||||
|
QNetworkRequest request(QString(endpoint.toEncoded()));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::removeTypingNotification(const QString &roomid)
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
QString user_id = settings.value("auth/user_id").toString();
|
||||||
|
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("access_token", token_);
|
||||||
|
|
||||||
|
QUrl endpoint(server_);
|
||||||
|
endpoint.setPath(clientApiUrl_ + QString("/rooms/%1/typing/%2").arg(roomid).arg(user_id));
|
||||||
|
|
||||||
|
endpoint.setQuery(query);
|
||||||
|
|
||||||
|
QString msgType("");
|
||||||
|
QJsonObject body;
|
||||||
|
|
||||||
|
body = {{"typing", false}};
|
||||||
|
|
||||||
|
QNetworkRequest request(QString(endpoint.toEncoded()));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
put(request, QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||||
|
}
|
||||||
|
@ -122,7 +122,16 @@ QuickSwitcher::QuickSwitcher(QWidget *parent)
|
|||||||
roomSearch_, &RoomSearchInput::hiding, this, [=]() { completer_->popup()->hide(); });
|
roomSearch_, &RoomSearchInput::hiding, this, [=]() { completer_->popup()->hide(); });
|
||||||
connect(roomSearch_, &QLineEdit::returnPressed, this, [=]() {
|
connect(roomSearch_, &QLineEdit::returnPressed, this, [=]() {
|
||||||
emit closing();
|
emit closing();
|
||||||
emit roomSelected(rooms_[this->roomSearch_->text().trimmed()]);
|
|
||||||
|
QString text("");
|
||||||
|
|
||||||
|
if (selection_ == -1) {
|
||||||
|
completer_->setCurrentRow(0);
|
||||||
|
text = completer_->currentCompletion();
|
||||||
|
} else {
|
||||||
|
text = this->roomSearch_->text().trimmed();
|
||||||
|
}
|
||||||
|
emit roomSelected(rooms_[text]);
|
||||||
|
|
||||||
roomSearch_->clear();
|
roomSearch_->clear();
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,7 @@ RegisterRequest::RegisterRequest(const QString &username, const QString &passwor
|
|||||||
QByteArray
|
QByteArray
|
||||||
RegisterRequest::serialize() noexcept
|
RegisterRequest::serialize() noexcept
|
||||||
{
|
{
|
||||||
QJsonObject body{ { "username", user_ }, { "password", password_ } };
|
QJsonObject body{{"username", user_}, {"password", password_}};
|
||||||
|
|
||||||
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, state_(state)
|
, state_(state)
|
||||||
, roomId_(room_id)
|
, roomId_(room_id)
|
||||||
, roomSettings_{ settings }
|
, roomSettings_{settings}
|
||||||
, isPressed_(false)
|
, isPressed_(false)
|
||||||
, maxHeight_(IconSize + 2 * Padding)
|
, maxHeight_(IconSize + 2 * Padding)
|
||||||
, unreadMsgCount_(0)
|
, unreadMsgCount_(0)
|
||||||
|
@ -33,12 +33,8 @@ RoomList::RoomList(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, client_(client)
|
, client_(client)
|
||||||
{
|
{
|
||||||
setStyleSheet("QWidget { border: none; }");
|
setStyleSheet(
|
||||||
|
"border: 1px solid #ccc; border-right: 0px solid #000; border-left: 0px solid #000;");
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
||||||
sizePolicy.setHorizontalStretch(0);
|
|
||||||
sizePolicy.setVerticalStretch(0);
|
|
||||||
setSizePolicy(sizePolicy);
|
|
||||||
|
|
||||||
topLayout_ = new QVBoxLayout(this);
|
topLayout_ = new QVBoxLayout(this);
|
||||||
topLayout_->setSpacing(0);
|
topLayout_->setSpacing(0);
|
||||||
@ -51,7 +47,7 @@ RoomList::RoomList(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
scrollArea_->setWidgetResizable(true);
|
scrollArea_->setWidgetResizable(true);
|
||||||
scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignTop | Qt::AlignVCenter);
|
scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignTop | Qt::AlignVCenter);
|
||||||
|
|
||||||
scrollAreaContents_ = new QWidget();
|
scrollAreaContents_ = new QWidget(this);
|
||||||
|
|
||||||
contentsLayout_ = new QVBoxLayout(scrollAreaContents_);
|
contentsLayout_ = new QVBoxLayout(scrollAreaContents_);
|
||||||
contentsLayout_->setSpacing(0);
|
contentsLayout_->setSpacing(0);
|
||||||
|
@ -5,13 +5,10 @@
|
|||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
|
|
||||||
SideBarActions::SideBarActions(QWidget *parent)
|
SideBarActions::SideBarActions(QWidget *parent)
|
||||||
: QWidget{ parent }
|
: QWidget{parent}
|
||||||
{
|
{
|
||||||
setFixedHeight(conf::sidebarActions::height);
|
setFixedHeight(conf::sidebarActions::height);
|
||||||
|
|
||||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
|
||||||
setSizePolicy(sizePolicy);
|
|
||||||
|
|
||||||
layout_ = new QHBoxLayout(this);
|
layout_ = new QHBoxLayout(this);
|
||||||
layout_->setMargin(0);
|
layout_->setMargin(0);
|
||||||
|
|
||||||
@ -45,6 +42,8 @@ SideBarActions::SideBarActions(QWidget *parent)
|
|||||||
layout_->addWidget(createRoomBtn_);
|
layout_->addWidget(createRoomBtn_);
|
||||||
layout_->addWidget(joinRoomBtn_);
|
layout_->addWidget(joinRoomBtn_);
|
||||||
layout_->addWidget(settingsBtn_);
|
layout_->addWidget(settingsBtn_);
|
||||||
|
|
||||||
|
connect(settingsBtn_, &QPushButton::clicked, this, &SideBarActions::showSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
SideBarActions::~SideBarActions() {}
|
SideBarActions::~SideBarActions() {}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QAbstractTextDocumentLayout>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@ -25,19 +26,143 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "TextInputWidget.h"
|
#include "TextInputWidget.h"
|
||||||
|
|
||||||
|
static constexpr size_t INPUT_HISTORY_SIZE = 127;
|
||||||
|
|
||||||
FilteredTextEdit::FilteredTextEdit(QWidget *parent)
|
FilteredTextEdit::FilteredTextEdit(QWidget *parent)
|
||||||
: QTextEdit(parent)
|
: QTextEdit{parent}
|
||||||
|
, history_index_{0}
|
||||||
{
|
{
|
||||||
|
connect(document()->documentLayout(),
|
||||||
|
&QAbstractTextDocumentLayout::documentSizeChanged,
|
||||||
|
this,
|
||||||
|
&FilteredTextEdit::updateGeometry);
|
||||||
|
QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
policy.setHeightForWidth(true);
|
||||||
|
setSizePolicy(policy);
|
||||||
|
working_history_.push_back("");
|
||||||
|
connect(this, &QTextEdit::textChanged, this, &FilteredTextEdit::textChanged);
|
||||||
setAcceptRichText(false);
|
setAcceptRichText(false);
|
||||||
|
|
||||||
|
typingTimer_ = new QTimer(this);
|
||||||
|
typingTimer_->setInterval(1000);
|
||||||
|
typingTimer_->setSingleShot(true);
|
||||||
|
|
||||||
|
connect(typingTimer_, &QTimer::timeout, this, &FilteredTextEdit::stopTyping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FilteredTextEdit::keyPressEvent(QKeyEvent *event)
|
FilteredTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
const bool isModifier = (event->modifiers() != Qt::NoModifier);
|
||||||
emit enterPressed();
|
|
||||||
else
|
if (!isModifier) {
|
||||||
|
if (!typingTimer_->isActive())
|
||||||
|
emit startedTyping();
|
||||||
|
|
||||||
|
typingTimer_->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event->key()) {
|
||||||
|
case Qt::Key_Return:
|
||||||
|
case Qt::Key_Enter:
|
||||||
|
if (!(event->modifiers() & Qt::ShiftModifier)) {
|
||||||
|
stopTyping();
|
||||||
|
submit();
|
||||||
|
} else {
|
||||||
QTextEdit::keyPressEvent(event);
|
QTextEdit::keyPressEvent(event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::Key_Up: {
|
||||||
|
auto initial_cursor = textCursor();
|
||||||
|
QTextEdit::keyPressEvent(event);
|
||||||
|
if (textCursor() == initial_cursor &&
|
||||||
|
history_index_ + 1 < working_history_.size()) {
|
||||||
|
++history_index_;
|
||||||
|
setPlainText(working_history_[history_index_]);
|
||||||
|
moveCursor(QTextCursor::End);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::Key_Down: {
|
||||||
|
auto initial_cursor = textCursor();
|
||||||
|
QTextEdit::keyPressEvent(event);
|
||||||
|
if (textCursor() == initial_cursor && history_index_ > 0) {
|
||||||
|
--history_index_;
|
||||||
|
setPlainText(working_history_[history_index_]);
|
||||||
|
moveCursor(QTextCursor::End);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
QTextEdit::keyPressEvent(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FilteredTextEdit::stopTyping()
|
||||||
|
{
|
||||||
|
typingTimer_->stop();
|
||||||
|
emit stoppedTyping();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize
|
||||||
|
FilteredTextEdit::sizeHint() const
|
||||||
|
{
|
||||||
|
ensurePolished();
|
||||||
|
auto margins = viewportMargins();
|
||||||
|
margins += document()->documentMargin();
|
||||||
|
QSize size = document()->size().toSize();
|
||||||
|
size.rwidth() += margins.left() + margins.right();
|
||||||
|
size.rheight() += margins.top() + margins.bottom();
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize
|
||||||
|
FilteredTextEdit::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
ensurePolished();
|
||||||
|
auto margins = viewportMargins();
|
||||||
|
margins += document()->documentMargin();
|
||||||
|
margins += contentsMargins();
|
||||||
|
QSize size(fontMetrics().averageCharWidth() * 10,
|
||||||
|
fontMetrics().lineSpacing() + margins.top() + margins.bottom());
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FilteredTextEdit::submit()
|
||||||
|
{
|
||||||
|
if (true_history_.size() == INPUT_HISTORY_SIZE)
|
||||||
|
true_history_.pop_back();
|
||||||
|
true_history_.push_front(toPlainText());
|
||||||
|
working_history_ = true_history_;
|
||||||
|
working_history_.push_front("");
|
||||||
|
history_index_ = 0;
|
||||||
|
|
||||||
|
QString text = toPlainText();
|
||||||
|
if (text.startsWith('/')) {
|
||||||
|
int command_end = text.indexOf(' ');
|
||||||
|
if (command_end == -1)
|
||||||
|
command_end = text.size();
|
||||||
|
auto name = text.mid(1, command_end - 1);
|
||||||
|
auto args = text.mid(command_end + 1);
|
||||||
|
if (name.isEmpty() || name == "/") {
|
||||||
|
message(args);
|
||||||
|
} else {
|
||||||
|
command(name, args);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message(std::move(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FilteredTextEdit::textChanged()
|
||||||
|
{
|
||||||
|
working_history_[history_index_] = toPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextInputWidget::TextInputWidget(QWidget *parent)
|
TextInputWidget::TextInputWidget(QWidget *parent)
|
||||||
@ -97,13 +222,18 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
|||||||
|
|
||||||
setLayout(topLayout_);
|
setLayout(topLayout_);
|
||||||
|
|
||||||
connect(sendMessageBtn_, SIGNAL(clicked()), this, SLOT(onSendButtonClicked()));
|
connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit);
|
||||||
connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection()));
|
connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection()));
|
||||||
connect(input_, SIGNAL(enterPressed()), sendMessageBtn_, SIGNAL(clicked()));
|
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
|
||||||
|
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
|
||||||
connect(emojiBtn_,
|
connect(emojiBtn_,
|
||||||
SIGNAL(emojiSelected(const QString &)),
|
SIGNAL(emojiSelected(const QString &)),
|
||||||
this,
|
this,
|
||||||
SLOT(addSelectedEmoji(const QString &)));
|
SLOT(addSelectedEmoji(const QString &)));
|
||||||
|
|
||||||
|
connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping);
|
||||||
|
|
||||||
|
connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -131,50 +261,13 @@ TextInputWidget::addSelectedEmoji(const QString &emoji)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TextInputWidget::onSendButtonClicked()
|
TextInputWidget::command(QString command, QString args)
|
||||||
{
|
{
|
||||||
auto msgText = input_->document()->toPlainText().trimmed();
|
if (command == "me") {
|
||||||
|
sendEmoteMessage(args);
|
||||||
if (msgText.isEmpty())
|
} else if (command == "join") {
|
||||||
return;
|
sendJoinRoomRequest(args);
|
||||||
|
|
||||||
if (msgText.startsWith(EMOTE_COMMAND)) {
|
|
||||||
auto text = parseEmoteCommand(msgText);
|
|
||||||
|
|
||||||
if (!text.isEmpty())
|
|
||||||
emit sendEmoteMessage(text);
|
|
||||||
} else if (msgText.startsWith(JOIN_COMMAND)) {
|
|
||||||
auto room = parseJoinCommand(msgText);
|
|
||||||
|
|
||||||
if (!room.isEmpty())
|
|
||||||
emit sendJoinRoomRequest(room);
|
|
||||||
} else {
|
|
||||||
emit sendTextMessage(msgText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input_->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
TextInputWidget::parseJoinCommand(const QString &cmd)
|
|
||||||
{
|
|
||||||
auto room = cmd.right(cmd.size() - JOIN_COMMAND.size()).trimmed();
|
|
||||||
|
|
||||||
if (!room.isEmpty())
|
|
||||||
return room;
|
|
||||||
|
|
||||||
return QString("");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
TextInputWidget::parseEmoteCommand(const QString &cmd)
|
|
||||||
{
|
|
||||||
auto text = cmd.right(cmd.size() - EMOTE_COMMAND.size()).trimmed();
|
|
||||||
|
|
||||||
if (!text.isEmpty())
|
|
||||||
return text;
|
|
||||||
|
|
||||||
return QString("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -226,6 +319,16 @@ TextInputWidget::hideUploadSpinner()
|
|||||||
spinner_->stop();
|
spinner_->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextInputWidget::~TextInputWidget()
|
TextInputWidget::~TextInputWidget() {}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextInputWidget::stopTyping()
|
||||||
{
|
{
|
||||||
|
input_->stopTyping();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextInputWidget::focusInEvent(QFocusEvent *event)
|
||||||
|
{
|
||||||
|
input_->setFocus(event->reason());
|
||||||
}
|
}
|
||||||
|
@ -85,15 +85,15 @@ TimelineItem::TimelineItem(events::MessageEventType ty,
|
|||||||
|
|
||||||
if (ty == events::MessageEventType::Emote) {
|
if (ty == events::MessageEventType::Emote) {
|
||||||
body = QString("* %1 %2").arg(displayName).arg(body);
|
body = QString("* %1 %2").arg(displayName).arg(body);
|
||||||
descriptionMsg_ = { "", userid, body, descriptiveTime(timestamp) };
|
descriptionMsg_ = {"", userid, body, descriptiveTime(timestamp)};
|
||||||
} else {
|
} else {
|
||||||
descriptionMsg_ = {
|
descriptionMsg_ = {
|
||||||
"You: ", userid, body, descriptiveTime(QDateTime::currentDateTime())
|
"You: ", userid, body, descriptiveTime(QDateTime::currentDateTime())};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body = body.toHtmlEscaped();
|
body = body.toHtmlEscaped();
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
body.replace("\n", "<br/>");
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
if (withSender) {
|
if (withSender) {
|
||||||
@ -114,14 +114,14 @@ TimelineItem::TimelineItem(ImageItem *image,
|
|||||||
const QString &userid,
|
const QString &userid,
|
||||||
bool withSender,
|
bool withSender,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget{ parent }
|
: QWidget{parent}
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
auto displayName = TimelineViewManager::displayName(userid);
|
auto displayName = TimelineViewManager::displayName(userid);
|
||||||
auto timestamp = QDateTime::currentDateTime();
|
auto timestamp = QDateTime::currentDateTime();
|
||||||
|
|
||||||
descriptionMsg_ = { "You", userid, " sent an image", descriptiveTime(timestamp) };
|
descriptionMsg_ = {"You", userid, " sent an image", descriptiveTime(timestamp)};
|
||||||
|
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
@ -158,10 +158,10 @@ TimelineItem::TimelineItem(ImageItem *image,
|
|||||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
|
descriptionMsg_ = {event.sender() == settings.value("auth/user_id") ? "You" : displayName,
|
||||||
event.sender(),
|
event.sender(),
|
||||||
" sent an image",
|
" sent an image",
|
||||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
|
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||||
|
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
@ -193,10 +193,10 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event,
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
descriptionMsg_ = { TimelineViewManager::displayName(event.sender()),
|
descriptionMsg_ = {TimelineViewManager::displayName(event.sender()),
|
||||||
event.sender(),
|
event.sender(),
|
||||||
" sent a notification",
|
" sent a notification",
|
||||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
|
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||||
|
|
||||||
auto body = event.content().body().trimmed().toHtmlEscaped();
|
auto body = event.content().body().trimmed().toHtmlEscaped();
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||||
@ -204,6 +204,7 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event,
|
|||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
body.replace("\n", "<br/>");
|
||||||
body = "<i style=\"color: #565E5E\">" + body + "</i>";
|
body = "<i style=\"color: #565E5E\">" + body + "</i>";
|
||||||
|
|
||||||
if (with_sender) {
|
if (with_sender) {
|
||||||
@ -238,14 +239,15 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Emote> &event,
|
|||||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
auto emoteMsg = QString("* %1 %2").arg(displayName).arg(body);
|
auto emoteMsg = QString("* %1 %2").arg(displayName).arg(body);
|
||||||
|
|
||||||
descriptionMsg_ = { "",
|
descriptionMsg_ = {"",
|
||||||
event.sender(),
|
event.sender(),
|
||||||
emoteMsg,
|
emoteMsg,
|
||||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
|
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||||
|
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
emoteMsg = emoteMsg.toHtmlEscaped();
|
emoteMsg = emoteMsg.toHtmlEscaped();
|
||||||
emoteMsg.replace(URL_REGEX, URL_HTML);
|
emoteMsg.replace(URL_REGEX, URL_HTML);
|
||||||
|
emoteMsg.replace("\n", "<br/>");
|
||||||
|
|
||||||
if (with_sender) {
|
if (with_sender) {
|
||||||
generateBody(displayName, emoteMsg);
|
generateBody(displayName, emoteMsg);
|
||||||
@ -276,15 +278,16 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event,
|
|||||||
auto displayName = TimelineViewManager::displayName(event.sender());
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
descriptionMsg_ = { event.sender() == settings.value("auth/user_id") ? "You" : displayName,
|
descriptionMsg_ = {event.sender() == settings.value("auth/user_id") ? "You" : displayName,
|
||||||
event.sender(),
|
event.sender(),
|
||||||
QString(": %1").arg(body),
|
QString(": %1").arg(body),
|
||||||
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp())) };
|
descriptiveTime(QDateTime::fromMSecsSinceEpoch(event.timestamp()))};
|
||||||
|
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
body = body.toHtmlEscaped();
|
body = body.toHtmlEscaped();
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
body.replace("\n", "<br/>");
|
||||||
|
|
||||||
if (with_sender) {
|
if (with_sender) {
|
||||||
generateBody(displayName, body);
|
generateBody(displayName, body);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@ -49,8 +50,8 @@ TimelineView::TimelineView(const Timeline &timeline,
|
|||||||
const QString &room_id,
|
const QString &room_id,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, room_id_{ room_id }
|
, room_id_{room_id}
|
||||||
, client_{ client }
|
, client_{client}
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
addEvents(timeline);
|
addEvents(timeline);
|
||||||
@ -60,8 +61,8 @@ TimelineView::TimelineView(QSharedPointer<MatrixClient> client,
|
|||||||
const QString &room_id,
|
const QString &room_id,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, room_id_{ room_id }
|
, room_id_{room_id}
|
||||||
, client_{ client }
|
, client_{client}
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
client_->messages(room_id_, "");
|
client_->messages(room_id_, "");
|
||||||
@ -179,6 +180,10 @@ TimelineView::addBackwardsEvents(const QString &room_id, const RoomMessages &msg
|
|||||||
isTimelineFinished = false;
|
isTimelineFinished = false;
|
||||||
QList<TimelineItem *> items;
|
QList<TimelineItem *> items;
|
||||||
|
|
||||||
|
// Reset the sender of the first message in the timeline
|
||||||
|
// cause we're about to insert a new one.
|
||||||
|
firstSender_.clear();
|
||||||
|
|
||||||
// Parse in reverse order to determine where we should not show sender's
|
// Parse in reverse order to determine where we should not show sender's
|
||||||
// name.
|
// name.
|
||||||
auto ii = msgs.chunk().size();
|
auto ii = msgs.chunk().size();
|
||||||
@ -241,9 +246,10 @@ TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection dire
|
|||||||
|
|
||||||
eventIds_[text.eventId()] = true;
|
eventIds_[text.eventId()] = true;
|
||||||
|
|
||||||
if (isPendingMessage(
|
QString txnid = text.unsignedData().transactionId();
|
||||||
text.eventId(), text.content().body(), text.sender(), local_user_)) {
|
if (!txnid.isEmpty() &&
|
||||||
removePendingMessage(text.eventId(), text.content().body());
|
isPendingMessage(txnid, text.sender(), local_user_)) {
|
||||||
|
removePendingMessage(txnid);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,9 +293,10 @@ TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection dire
|
|||||||
|
|
||||||
eventIds_[img.eventId()] = true;
|
eventIds_[img.eventId()] = true;
|
||||||
|
|
||||||
if (isPendingMessage(
|
QString txnid = img.unsignedData().transactionId();
|
||||||
img.eventId(), img.msgContent().url(), img.sender(), local_user_)) {
|
if (!txnid.isEmpty() &&
|
||||||
removePendingMessage(img.eventId(), img.msgContent().url());
|
isPendingMessage(txnid, img.sender(), local_user_)) {
|
||||||
|
removePendingMessage(txnid);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,11 +320,10 @@ TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection dire
|
|||||||
|
|
||||||
eventIds_[emote.eventId()] = true;
|
eventIds_[emote.eventId()] = true;
|
||||||
|
|
||||||
if (isPendingMessage(emote.eventId(),
|
QString txnid = emote.unsignedData().transactionId();
|
||||||
emote.content().body(),
|
if (!txnid.isEmpty() &&
|
||||||
emote.sender(),
|
isPendingMessage(txnid, emote.sender(), local_user_)) {
|
||||||
local_user_)) {
|
removePendingMessage(txnid);
|
||||||
removePendingMessage(emote.eventId(), emote.content().body());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,16 +501,16 @@ TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction)
|
|||||||
void
|
void
|
||||||
TimelineView::updatePendingMessage(int txn_id, QString event_id)
|
TimelineView::updatePendingMessage(int txn_id, QString event_id)
|
||||||
{
|
{
|
||||||
for (auto &msg : pending_msgs_) {
|
if (pending_msgs_.head().txn_id == txn_id) { // We haven't received it yet
|
||||||
if (msg.txn_id == txn_id) {
|
auto msg = pending_msgs_.dequeue();
|
||||||
msg.event_id = event_id;
|
msg.event_id = event_id;
|
||||||
break;
|
pending_sent_msgs_.append(msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sendNextPendingMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineView::addUserMessage(matrix::events::MessageEventType ty, const QString &body, int txn_id)
|
TimelineView::addUserMessage(matrix::events::MessageEventType ty, const QString &body)
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
auto user_id = settings.value("auth/user_id").toString();
|
auto user_id = settings.value("auth/user_id").toString();
|
||||||
@ -519,12 +525,13 @@ TimelineView::addUserMessage(matrix::events::MessageEventType ty, const QString
|
|||||||
|
|
||||||
lastSender_ = user_id;
|
lastSender_ = user_id;
|
||||||
|
|
||||||
PendingMessage message(txn_id, body, "", view_item);
|
int txn_id = client_->incrementTransactionId();
|
||||||
pending_msgs_.push_back(message);
|
PendingMessage message(ty, txn_id, body, "", "", view_item);
|
||||||
|
handleNewUserMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineView::addUserMessage(const QString &url, const QString &filename, int txn_id)
|
TimelineView::addUserMessage(const QString &url, const QString &filename)
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
auto user_id = settings.value("auth/user_id").toString();
|
auto user_id = settings.value("auth/user_id").toString();
|
||||||
@ -541,8 +548,36 @@ TimelineView::addUserMessage(const QString &url, const QString &filename, int tx
|
|||||||
|
|
||||||
lastSender_ = user_id;
|
lastSender_ = user_id;
|
||||||
|
|
||||||
PendingMessage message(txn_id, url, "", view_item);
|
int txn_id = client_->incrementTransactionId();
|
||||||
pending_msgs_.push_back(message);
|
PendingMessage message(
|
||||||
|
matrix::events::MessageEventType::Image, txn_id, url, filename, "", view_item);
|
||||||
|
handleNewUserMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineView::handleNewUserMessage(PendingMessage msg)
|
||||||
|
{
|
||||||
|
pending_msgs_.enqueue(msg);
|
||||||
|
if (pending_msgs_.size() == 1 && pending_sent_msgs_.size() == 0)
|
||||||
|
sendNextPendingMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineView::sendNextPendingMessage()
|
||||||
|
{
|
||||||
|
if (pending_msgs_.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PendingMessage &m = pending_msgs_.head();
|
||||||
|
switch (m.ty) {
|
||||||
|
case matrix::events::MessageEventType::Image:
|
||||||
|
client_->sendRoomMessage(
|
||||||
|
m.ty, m.txn_id, room_id_, QFileInfo(m.filename).fileName(), QFileInfo(m.filename), m.body);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
client_->sendRoomMessage(m.ty, m.txn_id, room_id_, m.body, QFileInfo());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -558,8 +593,7 @@ TimelineView::notifyForLastEvent()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TimelineView::isPendingMessage(const QString &eventid,
|
TimelineView::isPendingMessage(const QString &txnid,
|
||||||
const QString &body,
|
|
||||||
const QString &sender,
|
const QString &sender,
|
||||||
const QString &local_userid)
|
const QString &local_userid)
|
||||||
{
|
{
|
||||||
@ -567,7 +601,12 @@ TimelineView::isPendingMessage(const QString &eventid,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto &msg : pending_msgs_) {
|
for (const auto &msg : pending_msgs_) {
|
||||||
if (msg.event_id == eventid || msg.body == body)
|
if (QString::number(msg.txn_id) == txnid)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &msg : pending_sent_msgs_) {
|
||||||
|
if (QString::number(msg.txn_id) == txnid)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,14 +614,28 @@ TimelineView::isPendingMessage(const QString &eventid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineView::removePendingMessage(const QString &eventid, const QString &body)
|
TimelineView::removePendingMessage(const QString &txnid)
|
||||||
{
|
{
|
||||||
|
for (auto it = pending_sent_msgs_.begin(); it != pending_sent_msgs_.end(); ++it) {
|
||||||
|
if (QString::number(it->txn_id) == txnid) {
|
||||||
|
int index = std::distance(pending_sent_msgs_.begin(), it);
|
||||||
|
pending_sent_msgs_.removeAt(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); ++it) {
|
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); ++it) {
|
||||||
|
if (QString::number(it->txn_id) == txnid) {
|
||||||
int index = std::distance(pending_msgs_.begin(), it);
|
int index = std::distance(pending_msgs_.begin(), it);
|
||||||
|
|
||||||
if (it->event_id == eventid || it->body == body) {
|
|
||||||
pending_msgs_.removeAt(index);
|
pending_msgs_.removeAt(index);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineView::handleFailedMessage(int txnid)
|
||||||
|
{
|
||||||
|
Q_UNUSED(txnid);
|
||||||
|
// Note: We do this even if the message has already been echoed.
|
||||||
|
QTimer::singleShot(500, this, SLOT(sendNextPendingMessage()));
|
||||||
|
}
|
||||||
|
@ -31,10 +31,15 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<MatrixClient> client, QW
|
|||||||
: QStackedWidget(parent)
|
: QStackedWidget(parent)
|
||||||
, client_(client)
|
, client_(client)
|
||||||
{
|
{
|
||||||
setStyleSheet("QWidget { background: #fff; color: #e8e8e8; border: none;}");
|
setStyleSheet("border: none;");
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
client_.data(), &MatrixClient::messageSent, this, &TimelineViewManager::messageSent);
|
client_.data(), &MatrixClient::messageSent, this, &TimelineViewManager::messageSent);
|
||||||
|
|
||||||
|
connect(client_.data(),
|
||||||
|
&MatrixClient::messageSendFailed,
|
||||||
|
this,
|
||||||
|
&TimelineViewManager::messageSendFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineViewManager::~TimelineViewManager()
|
TimelineViewManager::~TimelineViewManager()
|
||||||
@ -53,28 +58,32 @@ TimelineViewManager::messageSent(const QString &event_id, const QString &roomid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::sendTextMessage(const QString &msg)
|
TimelineViewManager::messageSendFailed(const QString &roomid, int txn_id)
|
||||||
|
{
|
||||||
|
auto view = views_[roomid];
|
||||||
|
view->handleFailedMessage(txn_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::queueTextMessage(const QString &msg)
|
||||||
{
|
{
|
||||||
auto room_id = active_room_;
|
auto room_id = active_room_;
|
||||||
auto view = views_[room_id];
|
auto view = views_[room_id];
|
||||||
|
|
||||||
view->addUserMessage(matrix::events::MessageEventType::Text, msg, client_->transactionId());
|
view->addUserMessage(matrix::events::MessageEventType::Text, msg);
|
||||||
client_->sendRoomMessage(matrix::events::MessageEventType::Text, room_id, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::sendEmoteMessage(const QString &msg)
|
TimelineViewManager::queueEmoteMessage(const QString &msg)
|
||||||
{
|
{
|
||||||
auto room_id = active_room_;
|
auto room_id = active_room_;
|
||||||
auto view = views_[room_id];
|
auto view = views_[room_id];
|
||||||
|
|
||||||
view->addUserMessage(
|
view->addUserMessage(matrix::events::MessageEventType::Emote, msg);
|
||||||
matrix::events::MessageEventType::Emote, msg, client_->transactionId());
|
|
||||||
client_->sendRoomMessage(matrix::events::MessageEventType::Emote, room_id, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::sendImageMessage(const QString &roomid,
|
TimelineViewManager::queueImageMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
const QString &url)
|
const QString &url)
|
||||||
{
|
{
|
||||||
@ -85,9 +94,7 @@ TimelineViewManager::sendImageMessage(const QString &roomid,
|
|||||||
|
|
||||||
auto view = views_[roomid];
|
auto view = views_[roomid];
|
||||||
|
|
||||||
view->addUserMessage(url, filename, client_->transactionId());
|
view->addUserMessage(url, filename);
|
||||||
client_->sendRoomMessage(
|
|
||||||
matrix::events::MessageEventType::Image, roomid, QFileInfo(filename).fileName(), url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -196,7 +203,7 @@ QString
|
|||||||
TimelineViewManager::chooseRandomColor()
|
TimelineViewManager::chooseRandomColor()
|
||||||
{
|
{
|
||||||
std::random_device random_device;
|
std::random_device random_device;
|
||||||
std::mt19937 engine{ random_device() };
|
std::mt19937 engine{random_device()};
|
||||||
std::uniform_real_distribution<float> dist(0, 1);
|
std::uniform_real_distribution<float> dist(0, 1);
|
||||||
|
|
||||||
float hue = dist(engine);
|
float hue = dist(engine);
|
||||||
|
@ -30,11 +30,10 @@
|
|||||||
|
|
||||||
TopRoomBar::TopRoomBar(QWidget *parent)
|
TopRoomBar::TopRoomBar(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, buttonSize_{ 32 }
|
, buttonSize_{32}
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
setMinimumSize(QSize(0, 65));
|
setFixedHeight(65);
|
||||||
setStyleSheet("background-color: #fff; color: #171919;");
|
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout();
|
topLayout_ = new QHBoxLayout();
|
||||||
topLayout_->setSpacing(10);
|
topLayout_->setSpacing(10);
|
||||||
|
@ -123,9 +123,6 @@ TrayIcon::TrayIcon(const QString &filename, QWidget *parent)
|
|||||||
menu->addAction(quitAction_);
|
menu->addAction(quitAction_);
|
||||||
|
|
||||||
setContextMenu(menu);
|
setContextMenu(menu);
|
||||||
|
|
||||||
// We wait a little for the icon to load.
|
|
||||||
QTimer::singleShot(500, this, [=]() { show(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
TypingDisplay::TypingDisplay(QWidget *parent)
|
TypingDisplay::TypingDisplay(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, leftPadding_{ 24 }
|
, leftPadding_{24}
|
||||||
{
|
{
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPixelSize(conf::typingNotificationFontSize);
|
font.setPixelSize(conf::typingNotificationFontSize);
|
||||||
|
@ -29,13 +29,11 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, display_name_("User")
|
, display_name_("User")
|
||||||
, user_id_("@user:homeserver.org")
|
, user_id_("@user:homeserver.org")
|
||||||
, logoutModal_{ nullptr }
|
, logoutModal_{nullptr}
|
||||||
, logoutDialog_{ nullptr }
|
, logoutDialog_{nullptr}
|
||||||
, logoutButtonSize_{ 20 }
|
, logoutButtonSize_{20}
|
||||||
{
|
{
|
||||||
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
setFixedHeight(65);
|
||||||
setSizePolicy(sizePolicy);
|
|
||||||
setMinimumSize(QSize(0, 65));
|
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout(this);
|
topLayout_ = new QHBoxLayout(this);
|
||||||
topLayout_->setSpacing(0);
|
topLayout_->setSpacing(0);
|
||||||
@ -142,6 +140,8 @@ UserInfoWidget::resizeEvent(QResizeEvent *event)
|
|||||||
displayNameLabel_->show();
|
displayNameLabel_->show();
|
||||||
userIdLabel_->show();
|
userIdLabel_->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
155
src/UserSettingsPage.cc
Normal file
155
src/UserSettingsPage.cc
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "FlatButton.h"
|
||||||
|
#include "UserSettingsPage.h"
|
||||||
|
#include <ToggleButton.h>
|
||||||
|
|
||||||
|
UserSettings::UserSettings() { load(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
UserSettings::load()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
isTrayEnabled_ = settings.value("user/window/tray", true).toBool();
|
||||||
|
theme_ = settings.value("user/theme", "default").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserSettings::save()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup("user");
|
||||||
|
|
||||||
|
settings.beginGroup("window");
|
||||||
|
settings.setValue("tray", isTrayEnabled_);
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
|
settings.setValue("theme", theme());
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalLine::HorizontalLine(QWidget *parent)
|
||||||
|
: QFrame{parent}
|
||||||
|
{
|
||||||
|
setFrameShape(QFrame::HLine);
|
||||||
|
setFrameShadow(QFrame::Sunken);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent)
|
||||||
|
: QWidget{parent}
|
||||||
|
, settings_{settings}
|
||||||
|
{
|
||||||
|
topLayout_ = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
QIcon icon;
|
||||||
|
icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
|
||||||
|
|
||||||
|
auto backBtn_ = new FlatButton(this);
|
||||||
|
backBtn_->setMinimumSize(QSize(24, 24));
|
||||||
|
backBtn_->setIcon(icon);
|
||||||
|
backBtn_->setIconSize(QSize(24, 24));
|
||||||
|
|
||||||
|
auto heading_ = new QLabel(tr("User Settings"));
|
||||||
|
heading_->setFont(QFont("Open Sans Bold", 22));
|
||||||
|
|
||||||
|
topBarLayout_ = new QHBoxLayout;
|
||||||
|
topBarLayout_->setSpacing(0);
|
||||||
|
topBarLayout_->setMargin(0);
|
||||||
|
topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
topBarLayout_->addWidget(heading_, 0, Qt::AlignBottom);
|
||||||
|
topBarLayout_->addStretch(1);
|
||||||
|
|
||||||
|
auto trayOptionLayout_ = new QHBoxLayout;
|
||||||
|
trayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
|
||||||
|
auto trayLabel = new QLabel(tr("Minimize to tray"), this);
|
||||||
|
trayToggle_ = new Toggle(this);
|
||||||
|
trayToggle_->setActiveColor(QColor("#38A3D8"));
|
||||||
|
trayToggle_->setInactiveColor(QColor("gray"));
|
||||||
|
trayLabel->setFont(QFont("Open Sans", 15));
|
||||||
|
|
||||||
|
trayOptionLayout_->addWidget(trayLabel);
|
||||||
|
trayOptionLayout_->addWidget(trayToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||||
|
|
||||||
|
auto themeOptionLayout_ = new QHBoxLayout;
|
||||||
|
themeOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
|
||||||
|
auto themeLabel_ = new QLabel(tr("App theme"), this);
|
||||||
|
themeCombo_ = new QComboBox(this);
|
||||||
|
themeCombo_->addItem("Default");
|
||||||
|
themeCombo_->addItem("System");
|
||||||
|
themeLabel_->setFont(QFont("Open Sans", 15));
|
||||||
|
|
||||||
|
themeOptionLayout_->addWidget(themeLabel_);
|
||||||
|
themeOptionLayout_->addWidget(themeCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||||
|
|
||||||
|
auto general_ = new QLabel(tr("GENERAL"), this);
|
||||||
|
general_->setFont(QFont("Open Sans Bold", 17));
|
||||||
|
general_->setStyleSheet("color: #5d6565");
|
||||||
|
|
||||||
|
mainLayout_ = new QVBoxLayout;
|
||||||
|
mainLayout_->setSpacing(7);
|
||||||
|
mainLayout_->setContentsMargins(
|
||||||
|
sideMargin_, LayoutTopMargin, sideMargin_, LayoutBottomMargin);
|
||||||
|
mainLayout_->addWidget(general_, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
mainLayout_->addWidget(new HorizontalLine(this));
|
||||||
|
mainLayout_->addLayout(trayOptionLayout_);
|
||||||
|
mainLayout_->addWidget(new HorizontalLine(this));
|
||||||
|
mainLayout_->addLayout(themeOptionLayout_);
|
||||||
|
mainLayout_->addWidget(new HorizontalLine(this));
|
||||||
|
|
||||||
|
topLayout_->addLayout(topBarLayout_);
|
||||||
|
topLayout_->addLayout(mainLayout_);
|
||||||
|
topLayout_->addStretch(1);
|
||||||
|
|
||||||
|
connect(themeCombo_,
|
||||||
|
static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
|
||||||
|
[=](const QString &text) { settings_->setTheme(text.toLower()); });
|
||||||
|
|
||||||
|
connect(trayToggle_, &Toggle::toggled, this, [=](bool isDisabled) {
|
||||||
|
settings_->setTray(!isDisabled);
|
||||||
|
emit trayOptionChanged(!isDisabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(backBtn_, &QPushButton::clicked, this, [=]() {
|
||||||
|
settings_->save();
|
||||||
|
emit moveBack();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserSettingsPage::showEvent(QShowEvent *)
|
||||||
|
{
|
||||||
|
themeCombo_->setCurrentIndex((settings_->theme() == "default" ? 0 : 1));
|
||||||
|
trayToggle_->setState(!settings_->isTrayEnabled()); // Treats true as "off"
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserSettingsPage::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
sideMargin_ = width() * 0.2;
|
||||||
|
mainLayout_->setContentsMargins(
|
||||||
|
sideMargin_, LayoutTopMargin, sideMargin_, LayoutBottomMargin);
|
||||||
|
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
}
|
@ -78,3 +78,29 @@ matrix::events::isMessageEvent(EventType type)
|
|||||||
{
|
{
|
||||||
return type == EventType::RoomMessage;
|
return type == EventType::RoomMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
matrix::events::UnsignedData::deserialize(const QJsonValue &data)
|
||||||
|
{
|
||||||
|
if (!data.isObject())
|
||||||
|
throw DeserializationException("UnsignedData is not a JSON object");
|
||||||
|
|
||||||
|
auto object = data.toObject();
|
||||||
|
|
||||||
|
transaction_id_ = object.value("transaction_id").toString();
|
||||||
|
age_ = object.value("age").toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject
|
||||||
|
matrix::events::UnsignedData::serialize() const
|
||||||
|
{
|
||||||
|
QJsonObject object;
|
||||||
|
|
||||||
|
if (!transaction_id_.isEmpty())
|
||||||
|
object["transaction_id"] = transaction_id_;
|
||||||
|
|
||||||
|
if (age_ > 0)
|
||||||
|
object["age"] = age_;
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
29
src/main.cc
29
src/main.cc
@ -19,11 +19,38 @@
|
|||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
|
#include <QNetworkProxy>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
setupProxy()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
To set up a SOCKS proxy:
|
||||||
|
[user]
|
||||||
|
proxy\socks\host=<>
|
||||||
|
proxy\socks\port=<>
|
||||||
|
proxy\socks\user=<>
|
||||||
|
proxy\socks\password=<>
|
||||||
|
**/
|
||||||
|
if (settings.contains("user/proxy/socks/host")) {
|
||||||
|
QNetworkProxy proxy;
|
||||||
|
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||||
|
proxy.setHostName(settings.value("user/proxy/socks/host").toString());
|
||||||
|
proxy.setPort(settings.value("user/proxy/socks/port").toInt());
|
||||||
|
if (settings.contains("user/proxy/socks/user"))
|
||||||
|
proxy.setUser(settings.value("user/proxy/socks/user").toString());
|
||||||
|
if (settings.contains("user/proxy/socks/password"))
|
||||||
|
proxy.setPassword(settings.value("user/proxy/socks/password").toString());
|
||||||
|
QNetworkProxy::setApplicationProxy(proxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -62,6 +89,8 @@ main(int argc, char *argv[])
|
|||||||
appTranslator.load("nheko_" + lang, ":/translations");
|
appTranslator.load("nheko_" + lang, ":/translations");
|
||||||
app.installTranslator(&appTranslator);
|
app.installTranslator(&appTranslator);
|
||||||
|
|
||||||
|
setupProxy();
|
||||||
|
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
|
|
||||||
// Move the MainWindow to the center
|
// Move the MainWindow to the center
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
OverlayModal::OverlayModal(QWidget *parent, QWidget *content)
|
OverlayModal::OverlayModal(QWidget *parent, QWidget *content)
|
||||||
: OverlayWidget(parent)
|
: OverlayWidget(parent)
|
||||||
, duration_{ 500 }
|
, duration_{500}
|
||||||
, color_{ QColor(55, 55, 55) }
|
, color_{QColor(55, 55, 55)}
|
||||||
{
|
{
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
ScrollBar::ScrollBar(QScrollArea *area, QWidget *parent)
|
ScrollBar::ScrollBar(QScrollArea *area, QWidget *parent)
|
||||||
: QScrollBar(parent)
|
: QScrollBar(parent)
|
||||||
, area_{ area }
|
, area_{area}
|
||||||
{
|
{
|
||||||
hideTimer_.setSingleShot(true);
|
hideTimer_.setSingleShot(true);
|
||||||
|
|
||||||
|
@ -58,11 +58,17 @@ Theme::setColor(const QString &key, ui::Color color)
|
|||||||
static const QColor palette[] = {
|
static const QColor palette[] = {
|
||||||
QColor("#171919"),
|
QColor("#171919"),
|
||||||
|
|
||||||
QColor("#EBEBEB"), QColor("#C9C9C9"), QColor("#929292"),
|
QColor("#EBEBEB"),
|
||||||
|
QColor("#C9C9C9"),
|
||||||
|
QColor("#929292"),
|
||||||
|
|
||||||
QColor("#1C3133"), QColor("#577275"), QColor("#46A451"),
|
QColor("#1C3133"),
|
||||||
|
QColor("#577275"),
|
||||||
|
QColor("#46A451"),
|
||||||
|
|
||||||
QColor("#5D6565"), QColor("#E22826"), QColor("#81B3A9"),
|
QColor("#5D6565"),
|
||||||
|
QColor("#E22826"),
|
||||||
|
QColor("#81B3A9"),
|
||||||
|
|
||||||
rgba(0, 0, 0, 0),
|
rgba(0, 0, 0, 0),
|
||||||
};
|
};
|
||||||
|
212
src/ui/ToggleButton.cc
Normal file
212
src/ui/ToggleButton.cc
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#include <QApplication>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "ToggleButton.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle::Toggle(QWidget *parent)
|
||||||
|
: QAbstractButton{parent}
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
|
connect(this, &QAbstractButton::toggled, this, &Toggle::setState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setState(bool isEnabled)
|
||||||
|
{
|
||||||
|
thumb_->setShift(isEnabled ? Position::Right : Position::Left);
|
||||||
|
setupProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::init()
|
||||||
|
{
|
||||||
|
track_ = new ToggleTrack(this);
|
||||||
|
thumb_ = new ToggleThumb(this);
|
||||||
|
|
||||||
|
setCursor(QCursor(Qt::PointingHandCursor));
|
||||||
|
setCheckable(true);
|
||||||
|
setChecked(false);
|
||||||
|
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||||
|
|
||||||
|
setState(false);
|
||||||
|
setupProperties();
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setupProperties()
|
||||||
|
{
|
||||||
|
if (isEnabled()) {
|
||||||
|
Position position = thumb_->shift();
|
||||||
|
|
||||||
|
thumb_->setThumbColor(trackColor());
|
||||||
|
|
||||||
|
if (position == Position::Left)
|
||||||
|
track_->setTrackColor(activeColor());
|
||||||
|
else if (position == Position::Right)
|
||||||
|
track_->setTrackColor(inactiveColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setDisabledColor(const QColor &color)
|
||||||
|
{
|
||||||
|
disabledColor_ = color;
|
||||||
|
setupProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setActiveColor(const QColor &color)
|
||||||
|
{
|
||||||
|
activeColor_ = color;
|
||||||
|
setupProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setInactiveColor(const QColor &color)
|
||||||
|
{
|
||||||
|
inactiveColor_ = color;
|
||||||
|
setupProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Toggle::setTrackColor(const QColor &color)
|
||||||
|
{
|
||||||
|
trackColor_ = color;
|
||||||
|
setupProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleThumb::ToggleThumb(Toggle *parent)
|
||||||
|
: QWidget{parent}
|
||||||
|
, toggle_{parent}
|
||||||
|
, position_{Position::Right}
|
||||||
|
, offset_{0}
|
||||||
|
{
|
||||||
|
parent->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleThumb::setShift(Position position)
|
||||||
|
{
|
||||||
|
if (position_ != position) {
|
||||||
|
position_ = position;
|
||||||
|
updateOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ToggleThumb::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
const QEvent::Type type = event->type();
|
||||||
|
|
||||||
|
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||||
|
setGeometry(toggle_->rect().adjusted(8, 8, -8, -8));
|
||||||
|
updateOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleThumb::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event)
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
QBrush brush;
|
||||||
|
brush.setStyle(Qt::SolidPattern);
|
||||||
|
brush.setColor(toggle_->isEnabled() ? thumbColor_ : Qt::white);
|
||||||
|
|
||||||
|
painter.setBrush(brush);
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
|
||||||
|
int s;
|
||||||
|
QRectF r;
|
||||||
|
|
||||||
|
s = height() - 10;
|
||||||
|
r = QRectF(5 + offset_, 5, s, s);
|
||||||
|
|
||||||
|
painter.drawEllipse(r);
|
||||||
|
|
||||||
|
if (!toggle_->isEnabled()) {
|
||||||
|
brush.setColor(toggle_->disabledColor());
|
||||||
|
painter.setBrush(brush);
|
||||||
|
painter.drawEllipse(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleThumb::updateOffset()
|
||||||
|
{
|
||||||
|
const QSize s(size());
|
||||||
|
offset_ = position_ == Position::Left ? static_cast<qreal>(s.width() - s.height()) : 0;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleTrack::ToggleTrack(Toggle *parent)
|
||||||
|
: QWidget{parent}
|
||||||
|
, toggle_{parent}
|
||||||
|
{
|
||||||
|
Q_ASSERT(parent);
|
||||||
|
|
||||||
|
parent->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleTrack::setTrackColor(const QColor &color)
|
||||||
|
{
|
||||||
|
trackColor_ = color;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ToggleTrack::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
const QEvent::Type type = event->type();
|
||||||
|
|
||||||
|
if (QEvent::Resize == type || QEvent::Move == type) {
|
||||||
|
setGeometry(toggle_->rect());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ToggleTrack::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event)
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
QBrush brush;
|
||||||
|
if (toggle_->isEnabled()) {
|
||||||
|
brush.setColor(trackColor_);
|
||||||
|
painter.setOpacity(0.8);
|
||||||
|
} else {
|
||||||
|
brush.setColor(toggle_->disabledColor());
|
||||||
|
painter.setOpacity(0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
brush.setStyle(Qt::SolidPattern);
|
||||||
|
painter.setBrush(brush);
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
|
||||||
|
const int h = height() / 2;
|
||||||
|
const QRect r(0, h / 2, width(), h);
|
||||||
|
painter.drawRoundedRect(r.adjusted(14, 4, -14, -4), h / 2 - 4, h / 2 - 4);
|
||||||
|
}
|
246
tests/events.cc
246
tests/events.cc
@ -22,8 +22,8 @@ using namespace matrix::events;
|
|||||||
TEST(BaseEvent, Deserialization)
|
TEST(BaseEvent, Deserialization)
|
||||||
{
|
{
|
||||||
// NameEventContent
|
// NameEventContent
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "name", "Room Name" } } },
|
auto data =
|
||||||
{ "type", "m.room.name" } };
|
QJsonObject{{"content", QJsonObject{{"name", "Room Name"}}}, {"type", "m.room.name"}};
|
||||||
|
|
||||||
Event<NameEventContent> name_event;
|
Event<NameEventContent> name_event;
|
||||||
name_event.deserialize(data);
|
name_event.deserialize(data);
|
||||||
@ -31,47 +31,57 @@ TEST(BaseEvent, Deserialization)
|
|||||||
EXPECT_EQ(name_event.serialize(), data);
|
EXPECT_EQ(name_event.serialize(), data);
|
||||||
|
|
||||||
// TopicEventContent
|
// TopicEventContent
|
||||||
data = QJsonObject{ { "content", QJsonObject{ { "topic", "Room Topic" } } },
|
data = QJsonObject{{"content", QJsonObject{{"topic", "Room Topic"}}},
|
||||||
{ "type", "m.room.topic" } };
|
{"unsigned", QJsonObject{{"age", 22}, {"transaction_id", "randomid"}}},
|
||||||
|
{"type", "m.room.topic"}};
|
||||||
|
|
||||||
Event<TopicEventContent> topic_event;
|
Event<TopicEventContent> topic_event;
|
||||||
topic_event.deserialize(data);
|
topic_event.deserialize(data);
|
||||||
EXPECT_EQ(topic_event.content().topic(), "Room Topic");
|
EXPECT_EQ(topic_event.content().topic(), "Room Topic");
|
||||||
|
EXPECT_EQ(topic_event.unsignedData().age(), 22);
|
||||||
|
EXPECT_EQ(topic_event.unsignedData().transactionId(), "randomid");
|
||||||
EXPECT_EQ(topic_event.serialize(), data);
|
EXPECT_EQ(topic_event.serialize(), data);
|
||||||
|
|
||||||
// AvatarEventContent
|
// AvatarEventContent
|
||||||
data = QJsonObject{ { "content", QJsonObject{ { "url", "https://matrix.org" } } },
|
data = QJsonObject{
|
||||||
{ "type", "m.room.avatar" } };
|
{"content", QJsonObject{{"url", "https://matrix.org"}}},
|
||||||
|
{"unsigned", QJsonObject{{"age", 1343434343}, {"transaction_id", "m33434.33"}}},
|
||||||
|
{"type", "m.room.avatar"}};
|
||||||
|
|
||||||
Event<AvatarEventContent> avatar_event;
|
Event<AvatarEventContent> avatar_event;
|
||||||
avatar_event.deserialize(data);
|
avatar_event.deserialize(data);
|
||||||
EXPECT_EQ(avatar_event.content().url().toString(), "https://matrix.org");
|
EXPECT_EQ(avatar_event.content().url().toString(), "https://matrix.org");
|
||||||
|
EXPECT_EQ(avatar_event.unsignedData().age(), 1343434343);
|
||||||
|
EXPECT_EQ(avatar_event.unsignedData().transactionId(), "m33434.33");
|
||||||
EXPECT_EQ(avatar_event.serialize(), data);
|
EXPECT_EQ(avatar_event.serialize(), data);
|
||||||
|
|
||||||
// AliasesEventContent
|
// AliasesEventContent
|
||||||
data =
|
data = QJsonObject{
|
||||||
QJsonObject{ { "content",
|
{"content",
|
||||||
QJsonObject{
|
QJsonObject{{"aliases", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}}},
|
||||||
{ "aliases", QJsonArray{ "#test:matrix.org", "#test2:matrix.org" } } } },
|
{"unsigned", QJsonObject{{"transaction_id", "m33434.33"}}},
|
||||||
{ "type", "m.room.aliases" } };
|
{"type", "m.room.aliases"}};
|
||||||
|
|
||||||
Event<AliasesEventContent> aliases_event;
|
Event<AliasesEventContent> aliases_event;
|
||||||
aliases_event.deserialize(data);
|
aliases_event.deserialize(data);
|
||||||
EXPECT_EQ(aliases_event.content().aliases().size(), 2);
|
EXPECT_EQ(aliases_event.content().aliases().size(), 2);
|
||||||
|
EXPECT_EQ(aliases_event.unsignedData().transactionId(), "m33434.33");
|
||||||
EXPECT_EQ(aliases_event.serialize(), data);
|
EXPECT_EQ(aliases_event.serialize(), data);
|
||||||
|
|
||||||
// CreateEventContent
|
// CreateEventContent
|
||||||
data = QJsonObject{ { "content", QJsonObject{ { "creator", "@alice:matrix.org" } } },
|
data = QJsonObject{{"content", QJsonObject{{"creator", "@alice:matrix.org"}}},
|
||||||
{ "type", "m.room.create" } };
|
{"unsigned", QJsonObject{{"age", 2233}}},
|
||||||
|
{"type", "m.room.create"}};
|
||||||
|
|
||||||
Event<CreateEventContent> create_event;
|
Event<CreateEventContent> create_event;
|
||||||
create_event.deserialize(data);
|
create_event.deserialize(data);
|
||||||
EXPECT_EQ(create_event.content().creator(), "@alice:matrix.org");
|
EXPECT_EQ(create_event.content().creator(), "@alice:matrix.org");
|
||||||
|
EXPECT_EQ(create_event.unsignedData().age(), 2233);
|
||||||
EXPECT_EQ(create_event.serialize(), data);
|
EXPECT_EQ(create_event.serialize(), data);
|
||||||
|
|
||||||
// JoinRulesEventContent
|
// JoinRulesEventContent
|
||||||
data = QJsonObject{ { "content", QJsonObject{ { "join_rule", "private" } } },
|
data = QJsonObject{{"content", QJsonObject{{"join_rule", "private"}}},
|
||||||
{ "type", "m.room.join_rules" } };
|
{"type", "m.room.join_rules"}};
|
||||||
|
|
||||||
Event<JoinRulesEventContent> join_rules_event;
|
Event<JoinRulesEventContent> join_rules_event;
|
||||||
join_rules_event.deserialize(data);
|
join_rules_event.deserialize(data);
|
||||||
@ -81,27 +91,34 @@ TEST(BaseEvent, Deserialization)
|
|||||||
|
|
||||||
TEST(BaseEvent, DeserializationException)
|
TEST(BaseEvent, DeserializationException)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "rule", "private" } } },
|
auto data =
|
||||||
{ "type", "m.room.join_rules" } };
|
QJsonObject{{"content", QJsonObject{{"rule", "private"}}}, {"type", "m.room.join_rules"}};
|
||||||
|
|
||||||
Event<JoinRulesEventContent> event1;
|
Event<JoinRulesEventContent> event1;
|
||||||
ASSERT_THROW(event1.deserialize(data), DeserializationException);
|
ASSERT_THROW(event1.deserialize(data), DeserializationException);
|
||||||
|
|
||||||
data = QJsonObject{ { "contents", QJsonObject{ { "join_rule", "private" } } },
|
data = QJsonObject{{"contents", QJsonObject{{"join_rule", "private"}}},
|
||||||
{ "type", "m.room.join_rules" } };
|
{"type", "m.room.join_rules"}};
|
||||||
|
|
||||||
Event<JoinRulesEventContent> event2;
|
Event<JoinRulesEventContent> event2;
|
||||||
ASSERT_THROW(event2.deserialize(data), DeserializationException);
|
ASSERT_THROW(event2.deserialize(data), DeserializationException);
|
||||||
|
|
||||||
|
data = QJsonObject{{"contents", QJsonObject{{"join_rule", "private"}}},
|
||||||
|
{"unsigned", QJsonObject{{"age", "222"}}},
|
||||||
|
{"type", "m.room.join_rules"}};
|
||||||
|
|
||||||
|
Event<JoinRulesEventContent> event3;
|
||||||
|
ASSERT_THROW(event3.deserialize(data), DeserializationException);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RoomEvent, Deserialization)
|
TEST(RoomEvent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "name", "Name" } } },
|
auto data = QJsonObject{{"content", QJsonObject{{"name", "Name"}}},
|
||||||
{ "event_id", "$asdfafdf8af:matrix.org" },
|
{"event_id", "$asdfafdf8af:matrix.org"},
|
||||||
{ "room_id", "!aasdfaeae23r9:matrix.org" },
|
{"room_id", "!aasdfaeae23r9:matrix.org"},
|
||||||
{ "sender", "@alice:matrix.org" },
|
{"sender", "@alice:matrix.org"},
|
||||||
{ "origin_server_ts", 1323238293289323LL },
|
{"origin_server_ts", 1323238293289323LL},
|
||||||
{ "type", "m.room.name" } };
|
{"type", "m.room.name"}};
|
||||||
|
|
||||||
RoomEvent<NameEventContent> event;
|
RoomEvent<NameEventContent> event;
|
||||||
event.deserialize(data);
|
event.deserialize(data);
|
||||||
@ -116,11 +133,11 @@ TEST(RoomEvent, Deserialization)
|
|||||||
|
|
||||||
TEST(RoomEvent, DeserializationException)
|
TEST(RoomEvent, DeserializationException)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "name", "Name" } } },
|
auto data = QJsonObject{{"content", QJsonObject{{"name", "Name"}}},
|
||||||
{ "event_id", "$asdfafdf8af:matrix.org" },
|
{"event_id", "$asdfafdf8af:matrix.org"},
|
||||||
{ "room_id", "!aasdfaeae23r9:matrix.org" },
|
{"room_id", "!aasdfaeae23r9:matrix.org"},
|
||||||
{ "origin_server_ts", 1323238293289323LL },
|
{"origin_server_ts", 1323238293289323LL},
|
||||||
{ "type", "m.room.name" } };
|
{"type", "m.room.name"}};
|
||||||
|
|
||||||
RoomEvent<NameEventContent> event;
|
RoomEvent<NameEventContent> event;
|
||||||
|
|
||||||
@ -133,14 +150,14 @@ TEST(RoomEvent, DeserializationException)
|
|||||||
|
|
||||||
TEST(StateEvent, Deserialization)
|
TEST(StateEvent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "name", "Name" } } },
|
auto data = QJsonObject{{"content", QJsonObject{{"name", "Name"}}},
|
||||||
{ "event_id", "$asdfafdf8af:matrix.org" },
|
{"event_id", "$asdfafdf8af:matrix.org"},
|
||||||
{ "state_key", "some_state_key" },
|
{"state_key", "some_state_key"},
|
||||||
{ "prev_content", QJsonObject{ { "name", "Previous Name" } } },
|
{"prev_content", QJsonObject{{"name", "Previous Name"}}},
|
||||||
{ "room_id", "!aasdfaeae23r9:matrix.org" },
|
{"room_id", "!aasdfaeae23r9:matrix.org"},
|
||||||
{ "sender", "@alice:matrix.org" },
|
{"sender", "@alice:matrix.org"},
|
||||||
{ "origin_server_ts", 1323238293289323LL },
|
{"origin_server_ts", 1323238293289323LL},
|
||||||
{ "type", "m.room.name" } };
|
{"type", "m.room.name"}};
|
||||||
|
|
||||||
StateEvent<NameEventContent> event;
|
StateEvent<NameEventContent> event;
|
||||||
event.deserialize(data);
|
event.deserialize(data);
|
||||||
@ -157,13 +174,13 @@ TEST(StateEvent, Deserialization)
|
|||||||
|
|
||||||
TEST(StateEvent, DeserializationException)
|
TEST(StateEvent, DeserializationException)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "content", QJsonObject{ { "name", "Name" } } },
|
auto data = QJsonObject{{"content", QJsonObject{{"name", "Name"}}},
|
||||||
{ "event_id", "$asdfafdf8af:matrix.org" },
|
{"event_id", "$asdfafdf8af:matrix.org"},
|
||||||
{ "prev_content", QJsonObject{ { "name", "Previous Name" } } },
|
{"prev_content", QJsonObject{{"name", "Previous Name"}}},
|
||||||
{ "room_id", "!aasdfaeae23r9:matrix.org" },
|
{"room_id", "!aasdfaeae23r9:matrix.org"},
|
||||||
{ "sender", "@alice:matrix.org" },
|
{"sender", "@alice:matrix.org"},
|
||||||
{ "origin_server_ts", 1323238293289323LL },
|
{"origin_server_ts", 1323238293289323LL},
|
||||||
{ "type", "m.room.name" } };
|
{"type", "m.room.name"}};
|
||||||
|
|
||||||
StateEvent<NameEventContent> event;
|
StateEvent<NameEventContent> event;
|
||||||
|
|
||||||
@ -176,35 +193,30 @@ TEST(StateEvent, DeserializationException)
|
|||||||
|
|
||||||
TEST(EventType, Mapping)
|
TEST(EventType, Mapping)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.aliases" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.aliases"}}),
|
||||||
EventType::RoomAliases);
|
EventType::RoomAliases);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.avatar" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.avatar"}}), EventType::RoomAvatar);
|
||||||
EventType::RoomAvatar);
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.canonical_alias"}}),
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.canonical_alias" } }),
|
|
||||||
EventType::RoomCanonicalAlias);
|
EventType::RoomCanonicalAlias);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.create" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.create"}}), EventType::RoomCreate);
|
||||||
EventType::RoomCreate);
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.history_visibility"}}),
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.history_visibility" } }),
|
|
||||||
EventType::RoomHistoryVisibility);
|
EventType::RoomHistoryVisibility);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.join_rules" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.join_rules"}}),
|
||||||
EventType::RoomJoinRules);
|
EventType::RoomJoinRules);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.member" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.member"}}), EventType::RoomMember);
|
||||||
EventType::RoomMember);
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.message"}}),
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.message" } }),
|
|
||||||
EventType::RoomMessage);
|
EventType::RoomMessage);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.name" } }), EventType::RoomName);
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.name"}}), EventType::RoomName);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.power_levels" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.power_levels"}}),
|
||||||
EventType::RoomPowerLevels);
|
EventType::RoomPowerLevels);
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.topic" } }),
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.topic"}}), EventType::RoomTopic);
|
||||||
EventType::RoomTopic);
|
EXPECT_EQ(extractEventType(QJsonObject{{"type", "m.room.unknown"}}),
|
||||||
EXPECT_EQ(extractEventType(QJsonObject{ { "type", "m.room.unknown" } }),
|
|
||||||
EventType::Unsupported);
|
EventType::Unsupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AliasesEventContent, Deserialization)
|
TEST(AliasesEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data =
|
auto data = QJsonObject{{"aliases", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}};
|
||||||
QJsonObject{ { "aliases", QJsonArray{ "#test:matrix.org", "#test2:matrix.org" } } };
|
|
||||||
|
|
||||||
AliasesEventContent content;
|
AliasesEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -215,7 +227,7 @@ TEST(AliasesEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(AliasesEventContent, NotAnObject)
|
TEST(AliasesEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "#test:matrix.org", "#test2:matrix.org" };
|
auto data = QJsonArray{"#test:matrix.org", "#test2:matrix.org"};
|
||||||
|
|
||||||
AliasesEventContent content;
|
AliasesEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -223,7 +235,7 @@ TEST(AliasesEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(AliasesEventContent, MissingKey)
|
TEST(AliasesEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", QJsonArray{ "#test:matrix.org", "#test2:matrix.org" } } };
|
auto data = QJsonObject{{"key", QJsonArray{"#test:matrix.org", "#test2:matrix.org"}}};
|
||||||
|
|
||||||
AliasesEventContent content;
|
AliasesEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -237,7 +249,7 @@ TEST(AliasesEventContent, MissingKey)
|
|||||||
|
|
||||||
TEST(AvatarEventContent, Deserialization)
|
TEST(AvatarEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "url", "https://matrix.org/avatar.png" } };
|
auto data = QJsonObject{{"url", "https://matrix.org/avatar.png"}};
|
||||||
|
|
||||||
AvatarEventContent content;
|
AvatarEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -248,7 +260,7 @@ TEST(AvatarEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(AvatarEventContent, NotAnObject)
|
TEST(AvatarEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "key", "url" };
|
auto data = QJsonArray{"key", "url"};
|
||||||
|
|
||||||
AvatarEventContent content;
|
AvatarEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -256,7 +268,7 @@ TEST(AvatarEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(AvatarEventContent, MissingKey)
|
TEST(AvatarEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "https://matrix.org" } };
|
auto data = QJsonObject{{"key", "https://matrix.org"}};
|
||||||
|
|
||||||
AvatarEventContent content;
|
AvatarEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -270,7 +282,7 @@ TEST(AvatarEventContent, MissingKey)
|
|||||||
|
|
||||||
TEST(CreateEventContent, Deserialization)
|
TEST(CreateEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "creator", "@alice:matrix.org" } };
|
auto data = QJsonObject{{"creator", "@alice:matrix.org"}};
|
||||||
|
|
||||||
CreateEventContent content;
|
CreateEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -281,7 +293,7 @@ TEST(CreateEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(CreateEventContent, NotAnObject)
|
TEST(CreateEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "creator", "alice" };
|
auto data = QJsonArray{"creator", "alice"};
|
||||||
|
|
||||||
CreateEventContent content;
|
CreateEventContent content;
|
||||||
|
|
||||||
@ -290,7 +302,7 @@ TEST(CreateEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(CreateEventContent, MissingKey)
|
TEST(CreateEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "@alice:matrix.org" } };
|
auto data = QJsonObject{{"key", "@alice:matrix.org"}};
|
||||||
|
|
||||||
CreateEventContent content;
|
CreateEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -304,23 +316,23 @@ TEST(CreateEventContent, MissingKey)
|
|||||||
|
|
||||||
TEST(HistoryVisibilityEventContent, Deserialization)
|
TEST(HistoryVisibilityEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "history_visibility", "invited" } };
|
auto data = QJsonObject{{"history_visibility", "invited"}};
|
||||||
|
|
||||||
HistoryVisibilityEventContent content;
|
HistoryVisibilityEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Invited);
|
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Invited);
|
||||||
|
|
||||||
data = QJsonObject{ { "history_visibility", "joined" } };
|
data = QJsonObject{{"history_visibility", "joined"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Joined);
|
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Joined);
|
||||||
|
|
||||||
data = QJsonObject{ { "history_visibility", "shared" } };
|
data = QJsonObject{{"history_visibility", "shared"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Shared);
|
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::Shared);
|
||||||
|
|
||||||
data = QJsonObject{ { "history_visibility", "world_readable" } };
|
data = QJsonObject{{"history_visibility", "world_readable"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::WorldReadable);
|
EXPECT_EQ(content.historyVisibility(), HistoryVisibility::WorldReadable);
|
||||||
@ -328,7 +340,7 @@ TEST(HistoryVisibilityEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(HistoryVisibilityEventContent, NotAnObject)
|
TEST(HistoryVisibilityEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "history_visibility", "alice" };
|
auto data = QJsonArray{"history_visibility", "alice"};
|
||||||
|
|
||||||
HistoryVisibilityEventContent content;
|
HistoryVisibilityEventContent content;
|
||||||
|
|
||||||
@ -337,7 +349,7 @@ TEST(HistoryVisibilityEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(HistoryVisibilityEventContent, InvalidHistoryVisibility)
|
TEST(HistoryVisibilityEventContent, InvalidHistoryVisibility)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "history_visibility", "wrong" } };
|
auto data = QJsonObject{{"history_visibility", "wrong"}};
|
||||||
|
|
||||||
HistoryVisibilityEventContent content;
|
HistoryVisibilityEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -351,7 +363,7 @@ TEST(HistoryVisibilityEventContent, InvalidHistoryVisibility)
|
|||||||
|
|
||||||
TEST(HistoryVisibilityEventContent, MissingKey)
|
TEST(HistoryVisibilityEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "joined" } };
|
auto data = QJsonObject{{"key", "joined"}};
|
||||||
|
|
||||||
HistoryVisibilityEventContent content;
|
HistoryVisibilityEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -365,23 +377,23 @@ TEST(HistoryVisibilityEventContent, MissingKey)
|
|||||||
|
|
||||||
TEST(JoinRulesEventContent, Deserialization)
|
TEST(JoinRulesEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "join_rule", "invite" } };
|
auto data = QJsonObject{{"join_rule", "invite"}};
|
||||||
|
|
||||||
JoinRulesEventContent content;
|
JoinRulesEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.joinRule(), JoinRule::Invite);
|
EXPECT_EQ(content.joinRule(), JoinRule::Invite);
|
||||||
|
|
||||||
data = QJsonObject{ { "join_rule", "knock" } };
|
data = QJsonObject{{"join_rule", "knock"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.joinRule(), JoinRule::Knock);
|
EXPECT_EQ(content.joinRule(), JoinRule::Knock);
|
||||||
|
|
||||||
data = QJsonObject{ { "join_rule", "private" } };
|
data = QJsonObject{{"join_rule", "private"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.joinRule(), JoinRule::Private);
|
EXPECT_EQ(content.joinRule(), JoinRule::Private);
|
||||||
|
|
||||||
data = QJsonObject{ { "join_rule", "public" } };
|
data = QJsonObject{{"join_rule", "public"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.joinRule(), JoinRule::Public);
|
EXPECT_EQ(content.joinRule(), JoinRule::Public);
|
||||||
@ -389,7 +401,7 @@ TEST(JoinRulesEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(JoinRulesEventContent, NotAnObject)
|
TEST(JoinRulesEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "rule", "alice" };
|
auto data = QJsonArray{"rule", "alice"};
|
||||||
|
|
||||||
JoinRulesEventContent content;
|
JoinRulesEventContent content;
|
||||||
|
|
||||||
@ -398,7 +410,7 @@ TEST(JoinRulesEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(JoinRulesEventContent, InvalidHistoryVisibility)
|
TEST(JoinRulesEventContent, InvalidHistoryVisibility)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "join_rule", "wrong" } };
|
auto data = QJsonObject{{"join_rule", "wrong"}};
|
||||||
|
|
||||||
JoinRulesEventContent content;
|
JoinRulesEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -412,7 +424,7 @@ TEST(JoinRulesEventContent, InvalidHistoryVisibility)
|
|||||||
|
|
||||||
TEST(JoinRulesEventContent, MissingKey)
|
TEST(JoinRulesEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "invite" } };
|
auto data = QJsonObject{{"key", "invite"}};
|
||||||
|
|
||||||
JoinRulesEventContent content;
|
JoinRulesEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -426,7 +438,7 @@ TEST(JoinRulesEventContent, MissingKey)
|
|||||||
|
|
||||||
TEST(CanonicalAliasEventContent, Deserialization)
|
TEST(CanonicalAliasEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "alias", "Room Alias" } };
|
auto data = QJsonObject{{"alias", "Room Alias"}};
|
||||||
|
|
||||||
CanonicalAliasEventContent content;
|
CanonicalAliasEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -437,7 +449,7 @@ TEST(CanonicalAliasEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(CanonicalAliasEventContent, NotAnObject)
|
TEST(CanonicalAliasEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "alias", "Room Alias" };
|
auto data = QJsonArray{"alias", "Room Alias"};
|
||||||
|
|
||||||
CanonicalAliasEventContent content;
|
CanonicalAliasEventContent content;
|
||||||
|
|
||||||
@ -446,7 +458,7 @@ TEST(CanonicalAliasEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(CanonicalAliasEventContent, MissingKey)
|
TEST(CanonicalAliasEventContent, MissingKey)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "alias" } };
|
auto data = QJsonObject{{"key", "alias"}};
|
||||||
|
|
||||||
CanonicalAliasEventContent content;
|
CanonicalAliasEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -462,29 +474,29 @@ TEST(MemberEventContent, Deserialization)
|
|||||||
{
|
{
|
||||||
MemberEventContent content;
|
MemberEventContent content;
|
||||||
|
|
||||||
auto data = QJsonObject{ { "membership", "join" } };
|
auto data = QJsonObject{{"membership", "join"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.membershipState(), Membership::Join);
|
EXPECT_EQ(content.membershipState(), Membership::Join);
|
||||||
|
|
||||||
data = QJsonObject{ { "membership", "invite" }, { "displayname", "Username" } };
|
data = QJsonObject{{"membership", "invite"}, {"displayname", "Username"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.membershipState(), Membership::Invite);
|
EXPECT_EQ(content.membershipState(), Membership::Invite);
|
||||||
EXPECT_EQ(content.displayName(), "Username");
|
EXPECT_EQ(content.displayName(), "Username");
|
||||||
|
|
||||||
data = QJsonObject{ { "membership", "leave" }, { "avatar_url", "https://matrix.org" } };
|
data = QJsonObject{{"membership", "leave"}, {"avatar_url", "https://matrix.org"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.membershipState(), Membership::Leave);
|
EXPECT_EQ(content.membershipState(), Membership::Leave);
|
||||||
EXPECT_EQ(content.avatarUrl().toString(), "https://matrix.org");
|
EXPECT_EQ(content.avatarUrl().toString(), "https://matrix.org");
|
||||||
|
|
||||||
data = QJsonObject{ { "membership", "ban" } };
|
data = QJsonObject{{"membership", "ban"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.membershipState(), Membership::Ban);
|
EXPECT_EQ(content.membershipState(), Membership::Ban);
|
||||||
|
|
||||||
data = QJsonObject{ { "membership", "knock" } };
|
data = QJsonObject{{"membership", "knock"}};
|
||||||
|
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
EXPECT_EQ(content.membershipState(), Membership::Knock);
|
EXPECT_EQ(content.membershipState(), Membership::Knock);
|
||||||
@ -492,7 +504,7 @@ TEST(MemberEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(MemberEventContent, InvalidMembership)
|
TEST(MemberEventContent, InvalidMembership)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "membership", "wrong" } };
|
auto data = QJsonObject{{"membership", "wrong"}};
|
||||||
|
|
||||||
MemberEventContent content;
|
MemberEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -506,7 +518,7 @@ TEST(MemberEventContent, InvalidMembership)
|
|||||||
|
|
||||||
TEST(MemberEventContent, NotAnObject)
|
TEST(MemberEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "name", "join" };
|
auto data = QJsonArray{"name", "join"};
|
||||||
|
|
||||||
MemberEventContent content;
|
MemberEventContent content;
|
||||||
|
|
||||||
@ -515,7 +527,7 @@ TEST(MemberEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(MemberEventContent, MissingName)
|
TEST(MemberEventContent, MissingName)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "random" } };
|
auto data = QJsonObject{{"key", "random"}};
|
||||||
|
|
||||||
MemberEventContent content;
|
MemberEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -529,7 +541,7 @@ TEST(MemberEventContent, MissingName)
|
|||||||
|
|
||||||
TEST(NameEventContent, Deserialization)
|
TEST(NameEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "name", "Room Name" } };
|
auto data = QJsonObject{{"name", "Room Name"}};
|
||||||
|
|
||||||
NameEventContent content;
|
NameEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -540,7 +552,7 @@ TEST(NameEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(NameEventContent, NotAnObject)
|
TEST(NameEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "name", "Room Name" };
|
auto data = QJsonArray{"name", "Room Name"};
|
||||||
|
|
||||||
NameEventContent content;
|
NameEventContent content;
|
||||||
|
|
||||||
@ -549,7 +561,7 @@ TEST(NameEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(NameEventContent, MissingName)
|
TEST(NameEventContent, MissingName)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "Room Name" } };
|
auto data = QJsonObject{{"key", "Room Name"}};
|
||||||
|
|
||||||
NameEventContent content;
|
NameEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
@ -582,17 +594,17 @@ TEST(PowerLevelsEventContent, DefaultValues)
|
|||||||
TEST(PowerLevelsEventContent, FullDeserialization)
|
TEST(PowerLevelsEventContent, FullDeserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{
|
auto data = QJsonObject{
|
||||||
{ "ban", 1 },
|
{"ban", 1},
|
||||||
{ "invite", 2 },
|
{"invite", 2},
|
||||||
{ "kick", 3 },
|
{"kick", 3},
|
||||||
{ "redact", 4 },
|
{"redact", 4},
|
||||||
|
|
||||||
{ "events_default", 5 },
|
{"events_default", 5},
|
||||||
{ "state_default", 6 },
|
{"state_default", 6},
|
||||||
{ "users_default", 7 },
|
{"users_default", 7},
|
||||||
|
|
||||||
{ "events", QJsonObject{ { "m.message.text", 8 }, { "m.message.image", 9 } } },
|
{"events", QJsonObject{{"m.message.text", 8}, {"m.message.image", 9}}},
|
||||||
{ "users", QJsonObject{ { "@alice:matrix.org", 10 }, { "@bob:matrix.org", 11 } } },
|
{"users", QJsonObject{{"@alice:matrix.org", 10}, {"@bob:matrix.org", 11}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
PowerLevelsEventContent power_levels;
|
PowerLevelsEventContent power_levels;
|
||||||
@ -621,13 +633,13 @@ TEST(PowerLevelsEventContent, FullDeserialization)
|
|||||||
TEST(PowerLevelsEventContent, PartialDeserialization)
|
TEST(PowerLevelsEventContent, PartialDeserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{
|
auto data = QJsonObject{
|
||||||
{ "ban", 1 },
|
{"ban", 1},
|
||||||
{ "invite", 2 },
|
{"invite", 2},
|
||||||
|
|
||||||
{ "events_default", 5 },
|
{"events_default", 5},
|
||||||
{ "users_default", 7 },
|
{"users_default", 7},
|
||||||
|
|
||||||
{ "users", QJsonObject{ { "@alice:matrix.org", 10 }, { "@bob:matrix.org", 11 } } },
|
{"users", QJsonObject{{"@alice:matrix.org", 10}, {"@bob:matrix.org", 11}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
PowerLevelsEventContent power_levels;
|
PowerLevelsEventContent power_levels;
|
||||||
@ -653,7 +665,7 @@ TEST(PowerLevelsEventContent, PartialDeserialization)
|
|||||||
|
|
||||||
TEST(PowerLevelsEventContent, NotAnObject)
|
TEST(PowerLevelsEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "test", "test2" };
|
auto data = QJsonArray{"test", "test2"};
|
||||||
|
|
||||||
PowerLevelsEventContent power_levels;
|
PowerLevelsEventContent power_levels;
|
||||||
|
|
||||||
@ -662,7 +674,7 @@ TEST(PowerLevelsEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(TopicEventContent, Deserialization)
|
TEST(TopicEventContent, Deserialization)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "topic", "Room Topic" } };
|
auto data = QJsonObject{{"topic", "Room Topic"}};
|
||||||
|
|
||||||
TopicEventContent content;
|
TopicEventContent content;
|
||||||
content.deserialize(data);
|
content.deserialize(data);
|
||||||
@ -673,7 +685,7 @@ TEST(TopicEventContent, Deserialization)
|
|||||||
|
|
||||||
TEST(TopicEventContent, NotAnObject)
|
TEST(TopicEventContent, NotAnObject)
|
||||||
{
|
{
|
||||||
auto data = QJsonArray{ "topic", "Room Topic" };
|
auto data = QJsonArray{"topic", "Room Topic"};
|
||||||
|
|
||||||
TopicEventContent content;
|
TopicEventContent content;
|
||||||
|
|
||||||
@ -682,7 +694,7 @@ TEST(TopicEventContent, NotAnObject)
|
|||||||
|
|
||||||
TEST(TopicEventContent, MissingName)
|
TEST(TopicEventContent, MissingName)
|
||||||
{
|
{
|
||||||
auto data = QJsonObject{ { "key", "Room Name" } };
|
auto data = QJsonObject{{"key", "Room Name"}};
|
||||||
|
|
||||||
TopicEventContent content;
|
TopicEventContent content;
|
||||||
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
ASSERT_THROW(content.deserialize(data), DeserializationException);
|
||||||
|
Loading…
Reference in New Issue
Block a user