diff --git a/.gitmodules b/.gitmodules index 7692f4556..273336f84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,3 +36,8 @@ [submodule "retroshare-webui"] path = retroshare-webui url = https://github.com/RetroShare/RSNewWebUI.git + branch = master +[submodule "supportlibs/librnp"] + path = supportlibs/librnp + url = https://github.com/rnpgp/rnp.git + branch = main diff --git a/README.asciidoc b/README.asciidoc index e1f41e74d..6e5c52ce9 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -7,6 +7,9 @@ RetroShare is a decentralized, private, secure, cross-platform, communication toolkit. RetroShare provides file sharing, chat, messages, forums, channels and more. +|=============================================================================== +| Developer Documentation | image:https://deepwiki.com/badge.svg[link="https://deepwiki.com/RetroShare/RetroShare",title="Ask DeepWiki"] +|=============================================================================== .Build Status |=============================================================================== |GNU/Linux (via Gitlab CI) | image:https://gitlab.com/RetroShare/RetroShare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/RetroShare/-/commits/master",title="pipeline status"] diff --git a/RetroShare.pro b/RetroShare.pro index 944e8204e..4972fe2ab 100644 --- a/RetroShare.pro +++ b/RetroShare.pro @@ -25,9 +25,6 @@ CONFIG += c++14 TEMPLATE = subdirs -SUBDIRS += openpgpsdk -openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro - rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) { SUBDIRS += jsonapi-generator jsonapi-generator.file = jsonapi-generator/src/jsonapi-generator.pro @@ -36,7 +33,7 @@ rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) { SUBDIRS += libbitdht libbitdht.file = libbitdht/src/libbitdht.pro -libretroshare.depends += openpgpsdk libbitdht +libretroshare.depends += libbitdht SUBDIRS += libretroshare libretroshare.file = libretroshare/src/libretroshare.pro diff --git a/build_scripts/OSX/MacOS_X_InstallGuide.md b/build_scripts/OSX/MacOS_X_InstallGuide.md index 4afa90e2c..b63b12185 100644 --- a/build_scripts/OSX/MacOS_X_InstallGuide.md +++ b/build_scripts/OSX/MacOS_X_InstallGuide.md @@ -2,13 +2,15 @@ ## Qt Installation -Install Qt via: [Qt Download](http://www.qt.io/download/) +Qt 5.15 is not available as install package. -Use default options. And add Qt Script support. +Download Qt 5.15.x from here: [Qt 5.15.17](https://download.qt.io/archive/qt/5.15/5.15.17/single/qt-everywhere-opensource-src-5.15.17.tar.xz) +Instruction howto Build Qt 5.15.x on macOS: [macOS Building](https://doc.qt.io/archives/qt-5.15/macos-building.html) +## Set the Environment Variables Add to the PATH environment variable by editing your *~/.profile* file. - export PATH="/users/$USER/Qt/5.14.1/clang_64/bin:$PATH" + export PATH="/users/$USER/Qt/5.15.17/clang_64/bin:$PATH" Depends on which version of Qt you use. @@ -32,11 +34,9 @@ In GitHub Desktop -> Clone Repository -> URL ## ***Get XCode & MacOSX SDK*** -Install XCode following this guide: [XCode](http://guide.macports.org/#installing.xcode) - To identify the correct version of Xcode to install, you need to know which OS you are running. Go to the [x] menu -> "About This Mac" and read the macOS version number. -If you are running the macOS Catalina >= 10.15, you can install Xcode directly from App Store using the instructions below. +If you are running macOS Ventura 13.5 or later, you can install Xcode directly from App Store using the instructions below. You can find older versions of Xcode at [Apple Developer Downloads](https://developer.apple.com/downloads/). Find the appropriate .xip file for your macOS version @@ -53,27 +53,12 @@ Install XCode command line developer tools: Start XCode to get it updated and to able C compiler to create executables. -Get Your MacOSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs) - -## ***Choose if you use MacPort or HomeBrew*** +Older MacOSX SDK is available from here: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs) ### MacPort Installation Install MacPort following this guide: [MacPort](http://guide.macports.org/#installing.xcode) -#### Install libraries - - $ sudo port -v selfupdate - $ sudo port install openssl - $ sudo port install miniupnpc - -For VOIP Plugin: - - $ sudo port install speex-devel - $ sudo port install opencv - $ sudo port install ffmpeg - - ### HOMEBREW Installation Install HomeBrew following this guide: [HomeBrew](http://brew.sh/) @@ -85,6 +70,13 @@ Install HomeBrew following this guide: [HomeBrew](http://brew.sh/) $ brew install rapidjson $ brew install sqlcipher +For RNP lib: + + $ brew install bzip2 + $ brew install zlib + $ brew install json-c + $ brew install botan@2 + #### Install CMake $ brew install cmake diff --git a/build_scripts/OSX/makeOSXPackage.sh b/build_scripts/OSX/makeOSXPackage.sh index 24808d487..8f9700ed0 100644 --- a/build_scripts/OSX/makeOSXPackage.sh +++ b/build_scripts/OSX/makeOSXPackage.sh @@ -2,7 +2,7 @@ APP="RetroShare" RSVERSION="0.6.7a" -QTVERSION="Qt-5.14.1" +QTVERSION="Qt-5.15.11" # Install the 7z to create dmg archives. #brew list p7zip || brew install p7zip @@ -21,6 +21,7 @@ rm -rf qrc /usr/libexec/PlistBuddy -c "Delete :CFBundleGetInfoString" retroshare.app/Contents/Info.plist /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string $RSVERSION" retroshare.app/Contents/Info.plist /usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $RSVERSION" retroshare.app/Contents/Info.plist +/usr/libexec/PlistBuddy -c "Delete :NSRequiresAquaSystemAppearance" retroshare.app/Contents/Info.plist # This automatically creates retroshare.dmg diff --git a/build_scripts/RedHat+Fedora/data/retroshare.desktop b/build_scripts/RedHat+Fedora/data/retroshare.desktop index 7b93b4fa5..95056d54a 100644 --- a/build_scripts/RedHat+Fedora/data/retroshare.desktop +++ b/build_scripts/RedHat+Fedora/data/retroshare.desktop @@ -1,10 +1,11 @@ [Desktop Entry] +Encoding=UTF-8 Version=1.0 Name=RetroShare -Comment=Securely share files with your friends +Comment=Securely communicate with your friends Exec=/usr/bin/retroshare %U Icon=/usr/share/pixmaps/retroshare.xpm Terminal=false Type=Application -Categories=Network;P2P; +Categories=Network;Email;InstantMessaging;Chat;Feed;FileTransfer;P2P MimeType=x-scheme-handler/retroshare; diff --git a/build_scripts/Windows-msys2/build/build.bat b/build_scripts/Windows-msys2/build/build.bat index 4fdaff09f..bf68f3e20 100644 --- a/build_scripts/Windows-msys2/build/build.bat +++ b/build_scripts/Windows-msys2/build/build.bat @@ -18,6 +18,8 @@ if errorlevel 1 goto error_env if not "%ParamNoupdate%"=="1" ( :: Install needed things %EnvMSYS2Cmd% "pacman --noconfirm --needed -S make git mingw-w64-%RsMSYS2Architecture%-toolchain mingw-w64-%RsMSYS2Architecture%-qt5 mingw-w64-%RsMSYS2Architecture%-miniupnpc mingw-w64-%RsMSYS2Architecture%-sqlcipher mingw-w64-%RsMSYS2Architecture%-cmake mingw-w64-%RsMSYS2Architecture%-rapidjson" + :: rnp + %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-json-c mingw-w64-%RsMSYS2Architecture%-libbotan" :: Webui if "%ParamWebui%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-doxygen" diff --git a/build_scripts/Windows-msys2/build/pack.bat b/build_scripts/Windows-msys2/build/pack.bat index 313da7479..a898832f7 100644 --- a/build_scripts/Windows-msys2/build/pack.bat +++ b/build_scripts/Windows-msys2/build/pack.bat @@ -105,6 +105,7 @@ copy "%RsBuildPath%\retroshare-nogui\src\%RsBuildConfig%\retroshare*-nogui.exe" copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\supportlibs\cmark\build\src\libcmark.dll" "%RsDeployPath%" %Quite% if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite% +if exist "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" copy "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" "%RsDeployPath%" %Quite% if exist "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" ( copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite% ) diff --git a/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat b/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat index eaeba1482..cea1df073 100644 --- a/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat +++ b/build_scripts/Windows-msys2/env/tools/prepare-msys2.bat @@ -16,7 +16,7 @@ if "%~1"=="clean" ( goto exit ) -set MSYS2Version=20231026 +set MSYS2Version=20241208 set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install% diff --git a/build_scripts/Windows/build-libs/Makefile b/build_scripts/Windows/build-libs/Makefile index 0075770cd..534356914 100644 --- a/build_scripts/Windows/build-libs/Makefile +++ b/build_scripts/Windows/build-libs/Makefile @@ -13,12 +13,18 @@ LIBMICROHTTPD_VERSION=0.9.75 FFMPEG_VERSION=4.4 RAPIDJSON_VERSION=1.1.0 XAPIAN_VERSION=1.4.19 +#RNP_VERSION=0.17.1 + +# libaries for rnp +JSON_C_VERSION=0.18 +BOTAN_VERSION=2.19.5 DOWNLOAD_PATH?=download BUILD_PATH=build LIBS_PATH?=libs -all: dirs zlib bzip2 miniupnpc openssl speex speexdsp libxml2 libxslt curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian copylibs +all: dirs zlib bzip2 miniupnpc openssl speex speexdsp libxml2 libxslt curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian jsonc botan copylibs +#rnp download: \ $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz \ @@ -363,6 +369,57 @@ $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION): $(DOWNLOAD_PATH)/xapian-core-$(XAPI rm -r -f xapian-core-$(XAPIAN_VERSION) mv $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION).tmp $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION) +jsonc: $(BUILD_PATH)/json-c-$(JSON_C_VERSION) + +$(BUILD_PATH)/json-c-$(JSON_C_VERSION): + # prepare + rm -r -f $(BUILD_PATH)/json-c-* + [ -d "json-c-$(JSON_C_VERSION)" ] || git clone https://github.com/json-c/json-c.git --depth=1 --branch json-c-$(JSON_C_VERSION) "json-c-$(JSON_C_VERSION)" + # build + mkdir -p json-c-$(JSON_C_VERSION)/build + cd json-c-$(JSON_C_VERSION)/build && cmake .. -G"MSYS Makefiles" -Wno-dev -DCMAKE_BUILD_TYPE="release" -DBUILD_SHARED_LIBS=off -DBUILD_STATIC_LIBS=on -DBUILD_TESTING=off -DCMAKE_CXX_FLAGS="-D__MINGW_USE_VC2005_COMPAT" -DCMAKE_INSTALL_PREFIX="`pwd`/install" -DCMAKE_INSTALL_PREFIX="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION).tmp" + cd json-c-$(JSON_C_VERSION)/build && make install + # cleanup + rm -r -f json-c-$(JSON_C_VERSION) + mv $(BUILD_PATH)/json-c-$(JSON_C_VERSION).tmp $(BUILD_PATH)/json-c-$(JSON_C_VERSION) + +botan: $(BUILD_PATH)/botan-$(BOTAN_VERSION) + +$(BUILD_PATH)/botan-$(BOTAN_VERSION): + # prepare + pacman --needed --noconfirm -S python3 + rm -r -f $(BUILD_PATH)/botan-* + [ -d "botan-$(BOTAN_VERSION)" ] || git clone https://github.com/randombit/botan.git --depth=1 --branch $(BOTAN_VERSION) "botan-$(BOTAN_VERSION)" + # build + if [ $(MSYSTEM) = "MINGW32" ] ; then cd botan-$(BOTAN_VERSION) && ./configure.py --os=mingw --cpu=x86_32 --disable-shared-library --enable-static-library --extra-cxxflags="-D__MINGW_USE_VC2005_COMPAT" --prefix="`pwd`/../$(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp" ; fi + if [ $(MSYSTEM) = "MINGW64" ] ; then cd botan-$(BOTAN_VERSION) && ./configure.py --os=mingw --cpu=x86_64 --disable-shared-library --enable-static-library --prefix="`pwd`/../$(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp" ; fi + cd botan-$(BOTAN_VERSION) && make install + # cleanup + rm -r -f botan-$(BOTAN_VERSION) + mv $(BUILD_PATH)/botan-$(BOTAN_VERSION).tmp $(BUILD_PATH)/botan-$(BOTAN_VERSION) + +rnp: $(BUILD_PATH)/rnp-$(RNP_VERSION) + +$(BUILD_PATH)/rnp-$(RNP_VERSION): + # prepare + rm -r -f $(BUILD_PATH)/rnp-* + [ -d "rnp-$(RNP_VERSION)" ] || git clone https://github.com/rnpgp/rnp.git --depth=1 --branch v$(RNP_VERSION) --recurse-submodules --shallow-submodules "rnp-$(RNP_VERSION)" + # build + mkdir -p rnp-$(RNP_VERSION)/build + cd rnp-$(RNP_VERSION)/build && cmake .. -G"MSYS Makefiles" -Wno-dev -DCMAKE_INSTALL_PREFIX="`pwd`/install" -DBUILD_SHARED_LIBS=yes -DBUILD_TESTING=off -DCMAKE_CXX_FLAGS="-D__MINGW_USE_VC2005_COMPAT -D__STDC_FORMAT_MACROS" -DBZIP2_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/include" -DBZIP2_LIBRARY_RELEASE="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/lib/libbz2.a" -DBZIP2_LIBRARIES="`pwd`/../../$(BUILD_PATH)/bzip2-$(BZIP2_VERSION)/lib/libbz2.a" -DZLIB_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/zlib-$(ZLIB_VERSION)/include" -DZLIB_LIBRARY="`pwd`/../../$(BUILD_PATH)/zlib-$(ZLIB_VERSION)/lib/libz.a" -DJSON-C_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION)/include/json-c" -DJSON-C_LIBRARY="`pwd`/../../$(BUILD_PATH)/json-c-$(JSON_C_VERSION)/lib/libjson-c.a" -DBOTAN_INCLUDE_DIR="`pwd`/../../$(BUILD_PATH)/botan-$(BOTAN_VERSION)/include/botan-`echo $(BOTAN_VERSION) | cut -c1-1`" -DBOTAN_LIBRARY="`pwd`/../../$(BUILD_PATH)/botan-$(BOTAN_VERSION)/lib/libbotan-`echo $(BOTAN_VERSION) | cut -c1-1`.a" + cmake --build rnp-$(RNP_VERSION)/build + # copy files + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp + cp -r rnp-$(RNP_VERSION)/include/rnp/* $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp/ + cp -r rnp-$(RNP_VERSION)/build/src/lib/rnp/* $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/include/rnp/ + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/lib + cp -r rnp-$(RNP_VERSION)/build/src/lib/librnp.dll.a $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/lib/ + mkdir -p $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/bin + cp -r rnp-$(RNP_VERSION)/build/src/lib/librnp.dll $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp/bin/ + # cleanup + rm -r -f rnp-$(RNP_VERSION) + mv $(BUILD_PATH)/rnp-$(RNP_VERSION).tmp $(BUILD_PATH)/rnp-$(RNP_VERSION) + copylibs: rm -r -f $(LIBS_PATH) ; \ mkdir -p $(LIBS_PATH) ; \ diff --git a/build_scripts/Windows/build/pack.bat b/build_scripts/Windows/build/pack.bat index 1c844efa0..ff347babf 100644 --- a/build_scripts/Windows/build/pack.bat +++ b/build_scripts/Windows/build/pack.bat @@ -96,6 +96,7 @@ copy nul "%RsDeployPath%\portable" %Quite% echo copy binaries copy "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare*.exe" "%RsDeployPath%" %Quite% if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite% +if exist "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" copy "%RsBuildPath%\supportlibs\librnp\Build\src\lib\librnp.dll" "%RsDeployPath%" %Quite% if "%ParamService%"=="1" ( copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% diff --git a/build_scripts/Windows/env/tools/prepare-msys2.bat b/build_scripts/Windows/env/tools/prepare-msys2.bat index 25f00ac30..ba2f12ce6 100644 --- a/build_scripts/Windows/env/tools/prepare-msys2.bat +++ b/build_scripts/Windows/env/tools/prepare-msys2.bat @@ -16,13 +16,13 @@ if "%~1"=="clean" ( goto exit ) -set MSYS2Version=20231026 +set MSYS2Version=20241208 set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install% set MSYS2UnpackPath=%EnvMSYS2Path%\msys64 -set CMakeInstall=cmake-3.19.0-win32-x86.zip -set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall% +set CMakeInstall=cmake-3.31.3-windows-i386.zip +set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" ( if "%~1"=="reinstall" ( diff --git a/build_scripts/Windows/env/tools/prepare-tools.bat b/build_scripts/Windows/env/tools/prepare-tools.bat index 88549faed..f088acfa8 100644 --- a/build_scripts/Windows/env/tools/prepare-tools.bat +++ b/build_scripts/Windows/env/tools/prepare-tools.bat @@ -19,9 +19,9 @@ set MinGitInstallPath=%EnvToolsPath%\MinGit set DoxygenInstall=doxygen-1.9.6.windows.x64.bin.zip set DoxygenUrl=https://github.com/doxygen/doxygen/releases/download/Release_1_9_6/%DoxygenInstall% set DoxygenInstallPath=%EnvToolsPath%\doxygen -set CMakeVersion=cmake-3.19.0-win32-x86 +set CMakeVersion=cmake-3.31.3-windows-i386 set CMakeInstall=%CMakeVersion%.zip -set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall% +set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% set CMakeInstallPath=%EnvToolsPath%\cmake set TorProjectUrl=https://www.torproject.org set TorDownloadIndexUrl=%TorProjectUrl%/download/tor diff --git a/build_scripts/Windows/installer/retroshare-Qt5.nsi b/build_scripts/Windows/installer/retroshare-Qt5.nsi index 63c81bbcc..c7a5b9554 100644 --- a/build_scripts/Windows/installer/retroshare-Qt5.nsi +++ b/build_scripts/Windows/installer/retroshare-Qt5.nsi @@ -247,6 +247,7 @@ Section $(Section_Main) Section_Main ; External binaries File "${EXTERNAL_LIB_DIR}\bin\miniupnpc.dll" + File "${RELEASEDIR}\supportlibs\librnp\Build\src\lib\librnp.dll" !if ${ARCHITECTURE} == "x86" File "${EXTERNAL_LIB_DIR}\bin\libcrypto-1_1.dll" File "${EXTERNAL_LIB_DIR}\bin\libssl-1_1.dll" diff --git a/data/retroshare.desktop b/data/retroshare.desktop index efc73dd6b..95056d54a 100644 --- a/data/retroshare.desktop +++ b/data/retroshare.desktop @@ -7,5 +7,5 @@ Exec=/usr/bin/retroshare %U Icon=/usr/share/pixmaps/retroshare.xpm Terminal=false Type=Application -Categories=Application;Network;P2P;Feed;Chat;InstantMessaging +Categories=Network;Email;InstantMessaging;Chat;Feed;FileTransfer;P2P MimeType=x-scheme-handler/retroshare; diff --git a/libretroshare b/libretroshare index 402f32eda..ac83e00ea 160000 --- a/libretroshare +++ b/libretroshare @@ -1 +1 @@ -Subproject commit 402f32eda026c3ec3e429b5fb842e87ebd985d73 +Subproject commit ac83e00ea7a26cd6cf57cefef745d6dcfd07e5da diff --git a/openpgpsdk b/openpgpsdk index b41667912..178aa8ebc 160000 --- a/openpgpsdk +++ b/openpgpsdk @@ -1 +1 @@ -Subproject commit b41667912751a453e8e5d4733215a0609277a26f +Subproject commit 178aa8ebcef47e3271d5a5ca5c07e45d3b71c81d diff --git a/plugins/FeedReader/gui/FeedReaderDialog.cpp b/plugins/FeedReader/gui/FeedReaderDialog.cpp index 08f390a09..87db9cf9c 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.cpp +++ b/plugins/FeedReader/gui/FeedReaderDialog.cpp @@ -129,6 +129,8 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n settingsChanged(); feedTreeItemActivated(NULL); + + mFontSizeHandler.registerFontSize(ui->feedTreeWidget); } FeedReaderDialog::~FeedReaderDialog() diff --git a/plugins/FeedReader/gui/FeedReaderDialog.h b/plugins/FeedReader/gui/FeedReaderDialog.h index 12e11ee7f..a9672bc76 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.h +++ b/plugins/FeedReader/gui/FeedReaderDialog.h @@ -23,6 +23,7 @@ #include #include "interface/rsFeedReader.h" +#include "util/FontSizeHandler.h" namespace Ui { class FeedReaderDialog; @@ -98,6 +99,8 @@ private: RsFeedReader *mFeedReader; FeedReaderNotify *mNotify; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::FeedReaderDialog *ui; }; diff --git a/plugins/FeedReader/gui/FeedReaderDialog.ui b/plugins/FeedReader/gui/FeedReaderDialog.ui index b6b004d69..440bb7736 100644 --- a/plugins/FeedReader/gui/FeedReaderDialog.ui +++ b/plugins/FeedReader/gui/FeedReaderDialog.ui @@ -57,10 +57,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp b/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp index 59f72103c..ec0e3d0e2 100644 --- a/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp +++ b/plugins/FeedReader/gui/FeedReaderMessageWidget.cpp @@ -154,6 +154,8 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader * ui->msgTreeWidget->installEventFilter(this); setFeedId(feedId); + + mFontSizeHandler.registerFontSize(ui->msgTreeWidget); } FeedReaderMessageWidget::~FeedReaderMessageWidget() diff --git a/plugins/FeedReader/gui/FeedReaderMessageWidget.h b/plugins/FeedReader/gui/FeedReaderMessageWidget.h index 1223b3b4e..40f16e29f 100644 --- a/plugins/FeedReader/gui/FeedReaderMessageWidget.h +++ b/plugins/FeedReader/gui/FeedReaderMessageWidget.h @@ -24,6 +24,7 @@ #include #include "interface/rsFeedReader.h" +#include "util/FontSizeHandler.h" namespace Ui { class FeedReaderMessageWidget; @@ -107,6 +108,8 @@ private: RsFeedReader *mFeedReader; FeedReaderNotify *mNotify; + FontSizeHandler mFontSizeHandler; + Ui::FeedReaderMessageWidget *ui; }; diff --git a/retroshare-friendserver/src/friendserver.cc b/retroshare-friendserver/src/friendserver.cc index 19c286256..3c80bba83 100644 --- a/retroshare-friendserver/src/friendserver.cc +++ b/retroshare-friendserver/src/friendserver.cc @@ -8,7 +8,11 @@ #include "pgp/pgpkeyutil.h" #include "pgp/rscertificate.h" +#ifdef USE_OPENPGPSDK #include "pgp/openpgpsdkhandler.h" +#else +#include "pgp/rnppgphandler.h" +#endif #include "friendserver.h" #include "friend_server/fsitem.h" @@ -393,7 +397,11 @@ FriendServer::FriendServer(const std::string& base_dir,const std::string& listen std::string pgp_private_keyring_path = RsDirUtil::makePath(base_dir,"pgp_private_keyring") ; // not used. std::string pgp_trustdb_path = RsDirUtil::makePath(base_dir,"pgp_trustdb") ; // not used. +#ifdef USE_OPENPGPSDK mPgpHandler = new OpenPGPSDKHandler(pgp_public_keyring_path,pgp_private_keyring_path,pgp_trustdb_path,pgp_lock_path); +#else + mPgpHandler = new RNPPGPHandler(pgp_public_keyring_path,pgp_private_keyring_path,pgp_trustdb_path,pgp_lock_path); +#endif // Random bias. Should be cryptographically safe. diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index 9682bc4c5..60ed255a8 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -230,6 +230,8 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags) int ltwH = misc::getFontSizeFactor("LobbyTreeWidget", 1.5).height(); ui.lobbyTreeWidget->setIconSize(QSize(ltwH,ltwH)); + + mFontSizeHandler.registerFontSize(ui.lobbyTreeWidget); } ChatLobbyWidget::~ChatLobbyWidget() @@ -420,7 +422,7 @@ static void updateItem(QTreeWidget *treeWidget, QTreeWidgetItem *item, ChatLobby if(lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) { tooltipstr += QObject::tr("\nSecurity: no anonymous IDs") ; - QColor foreground = QColor(0, 128, 0); // green + QColor foreground = QColor(16, 157, 0); // green for (int column = 0; column < COLUMN_COUNT; ++column) item->setData(column, Qt::ForegroundRole, foreground); } diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.h b/retroshare-gui/src/gui/ChatLobbyWidget.h index a5055788e..424780dac 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.h +++ b/retroshare-gui/src/gui/ChatLobbyWidget.h @@ -25,6 +25,7 @@ #include "chat/ChatLobbyUserNotify.h" #include "gui/gxs/GxsIdChooser.h" +#include "util/FontSizeHandler.h" #include @@ -146,6 +147,8 @@ private: QAbstractButton* myInviteYesButton; GxsIdChooser* myInviteIdChooser; + FontSizeHandler mFontSizeHandler; + /* UI - from Designer */ Ui::ChatLobbyWidget ui; }; diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.ui b/retroshare-gui/src/gui/ChatLobbyWidget.ui index 8f8e8f29d..b2f711b72 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.ui +++ b/retroshare-gui/src/gui/ChatLobbyWidget.ui @@ -73,7 +73,7 @@ - 12 + 12 75 true @@ -191,11 +191,6 @@ - - - 11 - - 16 @@ -464,7 +459,7 @@ LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
RSTreeWidget diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index b3d74d6c4..c5b7ba04d 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -38,6 +38,7 @@ #include "gui/common/RSTreeWidgetItem.h" #include "util/QtVersion.h" #include "util/qtthreadsutils.h" +#include "util/misc.h" #include #include @@ -201,10 +202,6 @@ SearchDialog::SearchDialog(QWidget *parent) ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder); - QFontMetricsF fontMetrics(ui.searchResultWidget->font()); - int iconHeight = fontMetrics.height() * 1.4; - ui.searchResultWidget->setIconSize(QSize(iconHeight, iconHeight)); - /* Set initial size the splitter */ QList sizes; sizes << 250 << width(); // Qt calculates the right sizes @@ -239,6 +236,8 @@ SearchDialog::SearchDialog(QWidget *parent) RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); }, mEventHandlerId, RsEventType::FILE_TRANSFER ); + mFontSizeHandler.registerFontSize(ui.searchSummaryWidget); + mFontSizeHandler.registerFontSize(ui.searchResultWidget, 1.4f); } SearchDialog::~SearchDialog() @@ -1041,7 +1040,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); setIconAndType(child, QString::fromUtf8(dir.name.c_str())); @@ -1066,7 +1065,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_TYPE_COL, tr("Folder")); @@ -1135,7 +1134,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_SOURCES_COL, QString::number(1)); child->setData(SR_SOURCES_COL, ROLE_SORT, 1); - child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_TYPE_COL, tr("Folder")); @@ -1327,9 +1326,11 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s item->setText(SR_SIZE_COL, QString::number(file.size)); item->setData(SR_SIZE_COL, ROLE_SORT, (qulonglong) file.size); - item->setText(SR_AGE_COL, QString::number(file.mtime)); - item->setData(SR_AGE_COL, ROLE_SORT, file.mtime); + item->setText(SR_AGE_COL, QString::number(file.mtime)); + item->setData(SR_AGE_COL, ROLE_SORT, file.mtime); item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + item->setTextAlignment( SR_AGE_COL, Qt::AlignCenter ); + int friendSource = 0; int anonymousSource = 0; if(searchType == FRIEND_SEARCH) @@ -1348,7 +1349,7 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s item->setText(SR_SOURCES_COL,modifiedResult); item->setToolTip(SR_SOURCES_COL, tr("Obtained via ")+QString::fromStdString(rsPeers->getPeerName(file.id)) ); item->setData(SR_SOURCES_COL, ROLE_SORT, fltRes); - item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight ); + item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); item->setText(SR_SEARCH_ID_COL, sid_hexa); QColor foreground; diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h index 8aa7bac64..0af53662b 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h @@ -25,6 +25,7 @@ #include "retroshare/rsevents.h" #include "ui_SearchDialog.h" #include "retroshare-gui/mainpage.h" +#include "util/FontSizeHandler.h" class AdvancedSearchDialog; class RSTreeWidgetItemCompareRole; @@ -173,6 +174,8 @@ private: QAction *collViewAct; QAction *collOpenAct; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::SearchDialog ui; diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui index cd79340dd..4c8f8c38b 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.ui @@ -23,10 +23,10 @@
- QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -399,8 +399,8 @@ border-image: url(:/images/closepressed.png) - + diff --git a/retroshare-gui/src/gui/FriendsDialog.ui b/retroshare-gui/src/gui/FriendsDialog.ui index 02408e382..a8e8217fc 100644 --- a/retroshare-gui/src/gui/FriendsDialog.ui +++ b/retroshare-gui/src/gui/FriendsDialog.ui @@ -102,7 +102,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -132,10 +132,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -401,8 +401,8 @@ - + diff --git a/retroshare-gui/src/gui/HomePage.cpp b/retroshare-gui/src/gui/HomePage.cpp index ff7622b4b..914fde3e9 100644 --- a/retroshare-gui/src/gui/HomePage.cpp +++ b/retroshare-gui/src/gui/HomePage.cpp @@ -27,11 +27,13 @@ #include "util/misc.h" #include "gui/notifyqt.h" +#include "gui/common/FilesDefs.h" #include "gui/msgs/MessageComposer.h" #include "gui/connect/ConnectFriendWizard.h" #include "gui/connect/ConfCertDialog.h" #include #include "gui/connect/FriendRecommendDialog.h" +#include "settings/rsharesettings.h" #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include @@ -135,6 +137,8 @@ HomePage::HomePage(QWidget *parent) : rsEvents->registerEventsHandler( [this](std::shared_ptr event) { handleEvent(event); }, mEventHandlerId, RsEventType::NETWORK ); updateOwnCert(); + + updateHomeLogo(); } void HomePage::handleEvent(std::shared_ptr e) @@ -377,3 +381,18 @@ void HomePage::openWebHelp() { QDesktopServices::openUrl(QUrl(QString("https://retrosharedocs.readthedocs.io/en/latest/"))); } + +void HomePage::showEvent(QShowEvent *event) +{ + if (!event->spontaneous()) { + updateHomeLogo(); + } +} + +void HomePage::updateHomeLogo() +{ + if (Settings->getSheetName() == ":Standard_Dark") + ui->label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":images/logo/logo_web_nobackground_black.png")); + else + ui->label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":images/logo/logo_web_nobackground.png")); +} diff --git a/retroshare-gui/src/gui/HomePage.h b/retroshare-gui/src/gui/HomePage.h index aa77ed1a3..2dfc62f82 100644 --- a/retroshare-gui/src/gui/HomePage.h +++ b/retroshare-gui/src/gui/HomePage.h @@ -51,6 +51,8 @@ public: void getOwnCert(QString& invite,QString& description) const; RetroshareInviteFlags currentInviteFlags() const ; + virtual void showEvent(QShowEvent *) override; + private slots: #ifdef DEAD_CODE void certContextMenu(QPoint); @@ -63,7 +65,8 @@ private slots: void addFriend(); void webMail(); void openWebHelp() ; - void recommendFriends(); + void recommendFriends(); + void updateHomeLogo(); private: Ui::HomePage *ui; diff --git a/retroshare-gui/src/gui/HomePage.ui b/retroshare-gui/src/gui/HomePage.ui index 5de0fa6fe..e716577b8 100644 --- a/retroshare-gui/src/gui/HomePage.ui +++ b/retroshare-gui/src/gui/HomePage.ui @@ -43,7 +43,6 @@ Courier New - 10 75 true @@ -88,7 +87,6 @@ - 11 75 true @@ -107,7 +105,7 @@ ... - + :/icons/help_64.png:/icons/help_64.png @@ -233,11 +231,6 @@
- - - 12 - - Open Source cross-platform, private and secure decentralized communication platform. @@ -317,11 +310,6 @@ private and secure decentralized communication platform. - - - 11 - - @@ -405,11 +393,6 @@ private and secure decentralized communication platform. - - - 11 - - Do you need help with Retroshare? @@ -424,8 +407,8 @@ private and secure decentralized communication platform. - + diff --git a/retroshare-gui/src/gui/Identity/IdDialog.cpp b/retroshare-gui/src/gui/Identity/IdDialog.cpp index 4793ff613..a2d588d3e 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.cpp +++ b/retroshare-gui/src/gui/Identity/IdDialog.cpp @@ -31,6 +31,8 @@ #include "IdDialog.h" #include "ui_IdDialog.h" #include "IdEditDialog.h" +#include "IdentityListModel.h" + #include "gui/RetroShareLink.h" #include "gui/chat/ChatDialog.h" #include "gui/Circles/CreateCircleDialog.h" @@ -50,7 +52,7 @@ #include "util/rsdebug.h" #include "retroshare/rsgxsflags.h" -#include "retroshare/rsmsgs.h" +#include "retroshare/rsmsgs.h" #include "retroshare/rspeers.h" #include "retroshare/rsservicecontrol.h" @@ -92,11 +94,6 @@ /**************************************************************** */ -#define RSID_COL_NICKNAME 0 -#define RSID_COL_KEYID 1 -#define RSID_COL_IDTYPE 2 -#define RSID_COL_VOTES 3 - #define RSIDREP_COL_NAME 0 #define RSIDREP_COL_OPINION 1 #define RSIDREP_COL_COMMENT 2 @@ -123,6 +120,7 @@ static const uint32_t SortRole = Qt::UserRole+1 ; +#ifdef TO_REMOVE // quick solution for RSID_COL_VOTES sorting class TreeWidgetItem : public QTreeWidgetItem { @@ -146,6 +144,60 @@ class TreeWidgetItem : public QTreeWidgetItem return data(column,Qt::DisplayRole).toString().toUpper() < other.data(column,Qt::DisplayRole).toString().toUpper(); } }; +#endif + +std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere + +class IdListSortFilterProxyModel: public QSortFilterProxyModel +{ +public: + explicit IdListSortFilterProxyModel(const QHeaderView *header,QObject *parent = NULL) + : QSortFilterProxyModel(parent) + , m_header(header) + , m_sortingEnabled(false), m_sortByState(false) + { + setDynamicSortFilter(false); // causes crashes when true. + } + + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override + { +// bool online1 = (left .data(RsFriendListModel::OnlineRole).toInt() != RS_STATUS_OFFLINE); +// bool online2 = (right.data(RsFriendListModel::OnlineRole).toInt() != RS_STATUS_OFFLINE); +// +// if((online1 != online2) && m_sortByState) +// return (m_header->sortIndicatorOrder()==Qt::AscendingOrder)?online1:online2 ; // always put online nodes first + +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Comparing index " << left << " with index " << right << std::endl; +#endif + return QSortFilterProxyModel::lessThan(left,right); + } + + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override + { + // do not show empty groups + + QModelIndex index = sourceModel()->index(source_row,0,source_parent); + + return index.data(RsIdentityListModel::FilterRole).toString() == RsIdentityListModel::FilterString ; + } + + void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override + { + if(m_sortingEnabled) + return QSortFilterProxyModel::sort(column,order) ; + } + + void setSortingEnabled(bool b) { m_sortingEnabled = b ; } + void setSortByState(bool b) { m_sortByState = b ; } + bool sortByState() const { return m_sortByState ; } + +private: + const QHeaderView *m_header ; + bool m_sortingEnabled; + bool m_sortByState; +}; + /** Constructor */ IdDialog::IdDialog(QWidget *parent) @@ -153,6 +205,8 @@ IdDialog::IdDialog(QWidget *parent) , mExternalBelongingCircleItem(NULL) , mExternalOtherCircleItem(NULL ) , mMyCircleItem(NULL) + , mLastSortColumn(RsIdentityListModel::COLUMN_THREAD_NAME) + , mLastSortOrder(Qt::SortOrder::AscendingOrder) , needUpdateIdsOnNextShow(true), needUpdateCirclesOnNextShow(true) // Update Ids and Circles on first show , ui(new Ui::IdDialog) { @@ -167,38 +221,29 @@ IdDialog::IdDialog(QWidget *parent) // This is used to grab the broadcast of changes from p3GxsCircles, which is discarded by the current dialog, since it expects data for p3Identity only. //mCirclesBroadcastBase = new RsGxsUpdateBroadcastBase(rsGxsCircles, this); //connect(mCirclesBroadcastBase, SIGNAL(fillDisplay(bool)), this, SLOT(updateCirclesDisplay(bool))); - - ownItem = new QTreeWidgetItem(); - ownItem->setText(RSID_COL_NICKNAME, tr("My own identities")); - ownItem->setFont(RSID_COL_NICKNAME, ui->idTreeWidget->font()); - ownItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); // this is in order to prevent displaying a reputaiton icon next to these items. - allItem = new QTreeWidgetItem(); - allItem->setText(RSID_COL_NICKNAME, tr("All")); - allItem->setFont(RSID_COL_NICKNAME, ui->idTreeWidget->font()); - allItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); + mIdListModel = new RsIdentityListModel(this); - contactsItem = new QTreeWidgetItem(); - contactsItem->setText(RSID_COL_NICKNAME, tr("My contacts")); - contactsItem->setFont(RSID_COL_NICKNAME, ui->idTreeWidget->font()); - contactsItem->setData(RSID_COL_VOTES, Qt::DecorationRole,0xff); + mProxyModel = new IdListSortFilterProxyModel(ui->idTreeWidget->header(),this); + mProxyModel->setSourceModel(mIdListModel); + mProxyModel->setSortRole(RsIdentityListModel::SortRole); + mProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + mProxyModel->setFilterRole(RsIdentityListModel::FilterRole); + mProxyModel->setFilterRegExp(QRegExp(RsIdentityListModel::FilterString)); - ui->idTreeWidget->insertTopLevelItem(0, ownItem); - ui->idTreeWidget->insertTopLevelItem(0, allItem); - ui->idTreeWidget->insertTopLevelItem(0, contactsItem ); + ui->idTreeWidget->setModel(mProxyModel); + //ui->idTreeWidget->setSelectionModel(new QItemSelectionModel(mProxyModel));// useless in Qt5. ui->treeWidget_membership->clear(); ui->treeWidget_membership->setItemDelegateForColumn(CIRCLEGROUP_CIRCLE_COL_GROUPNAME,new GxsIdTreeItemDelegate()); - /* Setup UI helper */ mStateHelper = new UIStateHelper(this); -// mStateHelper->addWidget(IDDIALOG_IDLIST, ui->idTreeWidget); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDLIST, ui->idTreeWidget, false); - mStateHelper->addClear(IDDIALOG_IDLIST, ui->idTreeWidget); - mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + connect(ui->idTreeWidget,SIGNAL(expanded(const QModelIndex&)),this,SLOT(trace_expanded(const QModelIndex&)),Qt::DirectConnection); + connect(ui->idTreeWidget,SIGNAL(collapsed(const QModelIndex&)),this,SLOT(trace_collapsed(const QModelIndex&)),Qt::DirectConnection); + mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -214,7 +259,7 @@ IdDialog::IdDialog(QWidget *parent) mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_positive); mStateHelper->addWidget(IDDIALOG_IDDETAILS, ui->label_negative); - mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + //mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -225,7 +270,7 @@ IdDialog::IdDialog(QWidget *parent) mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->overallOpinion_TF); mStateHelper->addLoadPlaceholder(IDDIALOG_IDDETAILS, ui->usageStatistics_TB); - mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); + //mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Nickname); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_PublishTS); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_KeyId); mStateHelper->addClear(IDDIALOG_IDDETAILS, ui->lineEdit_Type); @@ -248,17 +293,20 @@ IdDialog::IdDialog(QWidget *parent) connect(ui->editIdentity, SIGNAL(triggered()), this, SLOT(editIdentity())); connect(ui->chatIdentity, SIGNAL(triggered()), this, SLOT(chatIdentity())); - connect(ui->idTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelection())); - connect(ui->idTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint))); + connect(ui->idTreeWidget->selectionModel(),SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),this,SLOT(updateSelection(const QItemSelection&,const QItemSelection&))); + connect(ui->idTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(IdListCustomPopupMenu(QPoint))); + + ui->idTreeWidget->header()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->idTreeWidget->header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint))); connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(ui->ownOpinion_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(modifyReputation())); - + connect(ui->ownOpinion_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(modifyReputation())); + connect(ui->inviteButton, SIGNAL(clicked()), this, SLOT(sendInvite())); connect(ui->editButton, SIGNAL(clicked()), this, SLOT(editIdentity())); - connect( ui->idTreeWidget, &RSTreeWidget::itemDoubleClicked, - this, &IdDialog::chatIdentityItem ); + connect(ui->idTreeWidget, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(chatIdentityItem(QModelIndex&)) ); + connect(ui->idTreeWidget->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumn(int,Qt::SortOrder))); ui->editButton->hide(); @@ -269,12 +317,13 @@ IdDialog::IdDialog(QWidget *parent) /* Initialize splitter */ ui->mainSplitter->setStretchFactor(0, 0); ui->mainSplitter->setStretchFactor(1, 1); - + clearPerson(); +#ifdef TODO /* Add filter types */ - QMenu *idTWHMenu = new QMenu(tr("Show Items"), this); - ui->idTreeWidget->addContextMenuMenu(idTWHMenu); + QMenu *idTWHMenu = new QMenu(tr("Show Items"), this); + ui->idTreeWidget->addContextMenuMenu(idTWHMenu); QActionGroup *idTWHActionGroup = new QActionGroup(this); QAction *idTWHAction = new QAction(QIcon(),tr("All"), this); @@ -327,66 +376,51 @@ IdDialog::IdDialog(QWidget *parent) idTWHAction->setData(RSID_FILTER_BANNED); connect(idTWHAction, SIGNAL(toggled(bool)), this, SLOT(filterToggled(bool))); idTWHMenu->addAction(idTWHAction); - +#endif + QAction *CreateIDAction = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/person.png"),tr("Create new Identity"), this); connect(CreateIDAction, SIGNAL(triggered()), this, SLOT(addIdentity())); - + QAction *CreateCircleAction = new QAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/circles.png"),tr("Create new circle"), this); connect(CreateCircleAction, SIGNAL(triggered()), this, SLOT(createExternalCircle())); - + QMenu *menu = new QMenu(); menu->addAction(CreateIDAction); menu->addAction(CreateCircleAction); ui->toolButton_New->setMenu(menu); - - /* Add filter actions */ - QTreeWidgetItem *headerItem = ui->idTreeWidget->headerItem(); - QString headerText = headerItem->text(RSID_COL_NICKNAME); - ui->filterLineEdit->addFilter(QIcon(), headerText, RSID_COL_NICKNAME, QString("%1 %2").arg(tr("Search"), headerText)); - headerItem->setData(RSID_COL_VOTES,Qt::UserRole,tr("Reputation")); + QFontMetricsF fm(ui->idTreeWidget->font()) ; /* Set initial section sizes */ - QHeaderView * circlesheader = ui->treeWidget_membership->header () ; - circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QFontMetricsF(ui->idTreeWidget->font()).width("Circle name")*1.5) ; - ui->treeWidget_membership->setColumnWidth(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 270); - - ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RSID_COL_KEYID, tr("Search ID")); + QHeaderView * circlesheader = ui->treeWidget_membership->header () ; + circlesheader->resizeSection (CIRCLEGROUP_CIRCLE_COL_GROUPNAME, fm.width("Circle name")*1.5) ; + ui->treeWidget_membership->setColumnWidth(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 270); /* Setup tree */ - ui->idTreeWidget->sortByColumn(RSID_COL_NICKNAME, Qt::AscendingOrder); + //ui->idTreeWidget->sortByColumn(RsIdentityListModel::COLUMN_THREAD_NAME, Qt::AscendingOrder); - ui->idTreeWidget->enableColumnCustomize(true); - ui->idTreeWidget->setColumnCustomizable(RSID_COL_NICKNAME, false); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_ID, true); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_NAME, true); + ui->idTreeWidget->setColumnHidden(RsIdentityListModel::COLUMN_THREAD_ID, true); - ui->idTreeWidget->setColumnHidden(RSID_COL_IDTYPE, true); - ui->idTreeWidget->setColumnHidden(RSID_COL_KEYID, true); - - /* Set initial column width */ - int fontWidth = QFontMetricsF(ui->idTreeWidget->font()).width("W"); - ui->idTreeWidget->setColumnWidth(RSID_COL_NICKNAME, 14 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_KEYID, 20 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_IDTYPE, 18 * fontWidth); - ui->idTreeWidget->setColumnWidth(RSID_COL_VOTES, 2 * fontWidth); - ui->idTreeWidget->setItemDelegate(new RSElidedItemDelegate()); - ui->idTreeWidget->setItemDelegateForColumn( - RSID_COL_NICKNAME, - new GxsIdTreeItemDelegate()); - ui->idTreeWidget->setItemDelegateForColumn( - RSID_COL_VOTES, - new ReputationItemDelegate(RsReputationLevel(0xff))); + ui->idTreeWidget->setItemDelegateForColumn( RsIdentityListModel::COLUMN_THREAD_REPUTATION, new ReputationItemDelegate(RsReputationLevel(0xff))); /* Set header resize modes and initial section sizes */ QHeaderView * idheader = ui->idTreeWidget->header(); - QHeaderView_setSectionResizeModeColumn(idheader, RSID_COL_VOTES, QHeaderView::ResizeToContents); - idheader->setStretchLastSection(true); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_NAME, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_ID, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_OWNER_ID, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_OWNER_NAME, QHeaderView::Stretch); + QHeaderView_setSectionResizeModeColumn(idheader, RsIdentityListModel::COLUMN_THREAD_REPUTATION, QHeaderView::Fixed); + ui->idTreeWidget->setColumnWidth(RsIdentityListModel::COLUMN_THREAD_REPUTATION,fm.height()); + idheader->setStretchLastSection(false); - mStateHelper->setActive(IDDIALOG_IDDETAILS, false); + mStateHelper->setActive(IDDIALOG_IDDETAILS, false); mStateHelper->setActive(IDDIALOG_REPLIST, false); int H = misc::getFontSizeFactor("HelpButton").height(); - QString hlp_str = tr( + QString hlp_str = tr( "

  Identities

" "

In this tab you can create/edit pseudo-anonymous identities, and circles.

" "

Identities are used to securely identify your data: sign messages in chat lobbies, forum and channel posts," @@ -408,13 +442,42 @@ IdDialog::IdDialog(QWidget *parent) processSettings(true); // circles stuff - + //connect(ui->treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected())); connect(ui->treeWidget_membership, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CircleListCustomPopupMenu(QPoint))); connect(ui->autoBanIdentities_CB, SIGNAL(toggled(bool)), this, SLOT(toggleAutoBanIdentities(bool))); - updateIdTimer.setSingleShot(true); + updateIdTimer.setSingleShot(true); connect(&updateIdTimer, SIGNAL(timeout()), this, SLOT(updateIdList())); + + mFontSizeHandler.registerFontSize(ui->idTreeWidget, 0, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + + mIdListModel->setFontSize(fontSize); + }); + + mFontSizeHandler.registerFontSize(ui->treeWidget_membership, 0, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QTreeWidgetItemIterator it(ui->treeWidget_membership); + while (*it) { + QTreeWidgetItem *item = *it; +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES + if (item->parent()) + { +#endif + QFont font = item->font(CIRCLEGROUP_CIRCLE_COL_GROUPNAME); + font.setPointSize(fontSize); + + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, font); + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPID, font); + item->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, font); + +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES + } +#endif + ++it; + } + }); } void IdDialog::handleEvent_main_thread(std::shared_ptr event) @@ -429,17 +492,19 @@ void IdDialog::handleEvent_main_thread(std::shared_ptr event) switch(e->mIdentityEventCode) { case RsGxsIdentityEventCode::DELETED_IDENTITY: - case RsGxsIdentityEventCode::NEW_IDENTITY: + if(mId == e->mIdentityId) + { + mId.clear(); + updateIdentity(); + } + updateIdListRequest(); + break; + + case RsGxsIdentityEventCode::NEW_IDENTITY: case RsGxsIdentityEventCode::UPDATED_IDENTITY: if (isVisible()) - { - if(rsIdentity->isOwnId(RsGxsId(e->mIdentityId))) - updateIdList(); - else - updateIdTimer.start(3000); // use a timer for events not generated by local changes - } - else - needUpdateIdsOnNextShow = true; + updateIdListRequest(); // use a timer for events not generated by local changes which generally + // come in large herds. Allows to group multiple changes into a single UI update. if(!mId.isNull() && mId == e->mIdentityId) updateIdentity(); @@ -481,11 +546,11 @@ void IdDialog::clearPerson() { //QFontMetricsF f(ui->avLabel_Person->font()) ; - //ui->avLabel_Person->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/people.png").scaled(f.height()*4,f.height()*4,Qt::KeepAspectRatio,Qt::SmoothTransformation)); ui->headerTextLabel_Person->setText(tr("People")); ui->info_Frame_Invite->hide(); ui->avatarLabel->clear(); + ui->avatarLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/people.png")); whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(1); whileBlocking(ui->autoBanIdentities_CB)->setChecked(false); @@ -499,7 +564,7 @@ void IdDialog::toggleAutoBanIdentities(bool b) if(!id.isNull()) { rsReputations->banNode(id,b) ; - updateIdList(); + updateIdListRequest(); } } @@ -507,10 +572,10 @@ void IdDialog::updateCirclesDisplay() { if(RsAutoUpdatePage::eventsLocked()) return ; - + if(!isVisible()) return ; - + #ifdef ID_DEBUG std::cerr << "!!Updating circles display!" << std::endl; #endif @@ -655,7 +720,6 @@ void IdDialog::loadCircles(const std::list& groupInfo) { mExternalOtherCircleItem = new QTreeWidgetItem(); mExternalOtherCircleItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Other circles")); - mExternalOtherCircleItem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, ui->treeWidget_membership->font()); ui->treeWidget_membership->addTopLevelItem(mExternalOtherCircleItem); } @@ -663,7 +727,6 @@ void IdDialog::loadCircles(const std::list& groupInfo) { mExternalBelongingCircleItem = new QTreeWidgetItem(); mExternalBelongingCircleItem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, tr("Circles I belong to")); - mExternalBelongingCircleItem->setFont(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, ui->treeWidget_membership->font()); ui->treeWidget_membership->addTopLevelItem(mExternalBelongingCircleItem); } #endif @@ -920,16 +983,16 @@ void IdDialog::loadCircles(const std::list& groupInfo) bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) { -#ifdef CIRCLE_MEMBERSHIP_CATEGORIES +#ifdef CIRCLE_MEMBERSHIP_CATEGORIES if ((!item) || (!item->parent())) return false; - + QString coltext = (item->parent()->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()); id = RsGxsCircleId( coltext.toStdString()) ; #else if(!item) return false; - + QString coltext = (item->parent())? (item->parent()->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()) : (item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString()); id = RsGxsCircleId( coltext.toStdString()) ; #endif @@ -939,7 +1002,7 @@ bool IdDialog::getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) void IdDialog::showEvent(QShowEvent *s) { if (needUpdateIdsOnNextShow) - updateIdList(); + updateIdListRequest(); if (needUpdateCirclesOnNextShow) updateCircles(); @@ -958,19 +1021,19 @@ void IdDialog::createExternalCircle() void IdDialog::showEditExistingCircle() { RsGxsCircleId id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),id)) return ; - + uint32_t subscribe_flags = ui->treeWidget_membership->currentItem()->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); - + CreateCircleDialog dlg; - + dlg.editExistingId(RsGxsGroupId(id),true,!(subscribe_flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) ; dlg.exec(); } -void IdDialog::grantCircleMembership() +void IdDialog::grantCircleMembership() { RsGxsCircleId circle_id ; @@ -987,7 +1050,7 @@ void IdDialog::grantCircleMembership() }); } -void IdDialog::revokeCircleMembership() +void IdDialog::revokeCircleMembership() { RsGxsCircleId circle_id ; @@ -1016,22 +1079,22 @@ void IdDialog::revokeCircleMembership() }); } -void IdDialog::acceptCircleSubscription() +void IdDialog::acceptCircleSubscription() { RsGxsCircleId circle_id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id)) return; RsGxsId own_id(qobject_cast(sender())->data().toString().toStdString()); - + rsGxsCircles->requestCircleMembership(own_id,circle_id) ; } -void IdDialog::cancelCircleSubscription() -{ +void IdDialog::cancelCircleSubscription() +{ RsGxsCircleId circle_id ; - + if(!getItemCircleId(ui->treeWidget_membership->currentItem(),circle_id)) return; @@ -1039,14 +1102,14 @@ void IdDialog::cancelCircleSubscription() rsGxsCircles->cancelCircleMembership(own_id,circle_id) ; } - + void IdDialog::CircleListCustomPopupMenu( QPoint ) { QMenu contextMnu( this ); RsGxsCircleId circle_id ; QTreeWidgetItem *item = ui->treeWidget_membership->currentItem(); - + if(!getItemCircleId(item,circle_id)) return ; @@ -1054,7 +1117,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) RsGxsId item_id(item->data(CIRCLEGROUP_CIRCLE_COL_GROUPID,Qt::UserRole).toString().toStdString()); bool is_circle ; bool am_I_circle_admin = false ; - + if(item_id == RsGxsId(circle_id)) // is it a circle? { uint32_t group_flags = item->data(CIRCLEGROUP_CIRCLE_COL_GROUPFLAGS, Qt::UserRole).toUInt(); @@ -1073,7 +1136,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) #ifdef CIRCLE_MEMBERSHIP_CATEGORIES } #endif - + #ifdef ID_DEBUG std::cerr << " Item is a circle item. Adding Edit/Details menu entry." << std::endl; #endif @@ -1081,7 +1144,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) contextMnu.addSeparator() ; } - else + else { current_gxs_id = RsGxsId(item_id); is_circle =false ; @@ -1096,9 +1159,9 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) std::cerr << " Item is a GxsId item. Requesting flags/group id from parent: " << circle_id << std::endl; #endif } - + RsGxsCircleDetails details ; - + if(!rsGxsCircles->getCircleDetails(circle_id,details))// grab real circle ID from parent. Make sure circle id is used correctly afterwards! { std::cerr << " (EE) cannot get circle info for ID " << circle_id << ". Not in cache?" << std::endl; @@ -1135,7 +1198,7 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) ids[REMOVE].push_back(*it) ; else ids[CANCEL].push_back(*it) ; - else + else if(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ids[ACCEPT].push_back(*it) ; else @@ -1196,17 +1259,17 @@ void IdDialog::CircleListCustomPopupMenu( QPoint ) contextMnu.addMenu(menu) ; } } - + if(!is_circle && am_I_circle_admin) // I am circle admin. I can therefore revoke/accept membership { std::map::const_iterator it = details.mSubscriptionFlags.find(current_gxs_id) ; - + if(!current_gxs_id.isNull() && it != details.mSubscriptionFlags.end()) { contextMnu.addSeparator() ; if(it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) - { + { QAction *action = new QAction(tr("Revoke this member"),this) ; action->setData(QString::fromStdString(current_gxs_id.toStdString())); QObject::connect(action,SIGNAL(triggered()), this, SLOT(revokeCircleMembership())); @@ -1234,6 +1297,8 @@ IdDialog::~IdDialog() // save settings processSettings(false); + delete mIdListModel; + delete mProxyModel; delete(ui); } @@ -1251,46 +1316,65 @@ static QString getHumanReadableDuration(uint32_t seconds) return QString(QObject::tr("%1 hours ago")).arg(seconds/3600) ; else if(seconds < 2*24*3600) return QString(QObject::tr("%1 day ago")).arg(seconds/86400) ; - else + else return QString(QObject::tr("%1 days ago")).arg(seconds/86400) ; } void IdDialog::processSettings(bool load) { - Settings->beginGroup("IdDialog"); + Settings->beginGroup("IdDialog"); - // state of peer tree - ui->idTreeWidget->processSettings(load); + if (load) { + // load settings - if (load) { - // load settings + ui->idTreeWidget->header()->restoreState(Settings->value(objectName()).toByteArray()); + ui->idTreeWidget->header()->setHidden(Settings->value(objectName()+"HiddenHeader", false).toBool()); - // filterColumn - ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", RSID_COL_NICKNAME).toInt()); + // filterColumn + //ui->filterLineEdit->setCurrentFilter(Settings->value("filterColumn", RsIdentityListModel::COLUMN_THREAD_NAME).toInt()); - // state of splitter - ui->mainSplitter->restoreState(Settings->value("splitter").toByteArray()); + // state of splitter + ui->mainSplitter->restoreState(Settings->value("splitter").toByteArray()); - //Restore expanding - allItem->setExpanded(Settings->value("ExpandAll", QVariant(true)).toBool()); - ownItem->setExpanded(Settings->value("ExpandOwn", QVariant(true)).toBool()); - contactsItem->setExpanded(Settings->value("ExpandContacts", QVariant(true)).toBool()); - } else { - // save settings + //Restore expanding + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_ALL)),Settings->value("ExpandAll", QVariant(true)).toBool()); + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_OWN)),Settings->value("ExpandOwn", QVariant(true)).toBool()); + ui->idTreeWidget->setExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_CTS)),Settings->value("ExpandContacts", QVariant(true)).toBool()); - // filterColumn - Settings->setValue("filterColumn", ui->filterLineEdit->currentFilter()); + // visible columns - // state of splitter - Settings->setValue("splitter", ui->mainSplitter->saveState()); - - //save expanding - Settings->setValue("ExpandAll", allItem->isExpanded()); - Settings->setValue("ExpandContacts", contactsItem->isExpanded()); - Settings->setValue("ExpandOwn", ownItem->isExpanded()); - } + int v = Settings->value("columnVisibility",(1 << RsIdentityListModel::COLUMN_THREAD_NAME)+(1 << RsIdentityListModel::COLUMN_THREAD_REPUTATION)).toInt(); - Settings->endGroup(); + for(int i=0;icolumnCount();++i) + ui->idTreeWidget->setColumnHidden(i,!(v & (1<setValue(objectName(), ui->idTreeWidget->header()->saveState()); + Settings->setValue(objectName()+"HiddenHeader", ui->idTreeWidget->header()->isHidden()); + + // filterColumn + //Settings->setValue("filterColumn", ui->filterLineEdit->currentFilter()); + + // state of splitter + Settings->setValue("splitter", ui->mainSplitter->saveState()); + + //save expanding + Settings->setValue("ExpandAll", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_ALL)))); + Settings->setValue("ExpandContacts", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_CTS)))); + Settings->setValue("ExpandOwn", ui->idTreeWidget->isExpanded(mProxyModel->mapFromSource(mIdListModel->getIndexOfCategory(RsIdentityListModel::CATEGORY_OWN)))); + + int v = 0; + for(int i=0;icolumnCount();++i) + if(!ui->idTreeWidget->isColumnHidden(i)) + v += (1 << i); + + Settings->setValue("columnVisibility",v); + } + + Settings->endGroup(); } void IdDialog::filterChanged(const QString& /*text*/) @@ -1304,79 +1388,79 @@ void IdDialog::filterToggled(const bool &value) QAction *source = qobject_cast(QObject::sender()); if (source) { filter = source->data().toInt(); - updateIdList(); + updateIdListRequest(); } } } -void IdDialog::updateSelection() +void IdDialog::updateSelection(const QItemSelection& /* new_sel */,const QItemSelection& /* old_sel */) { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - RsGxsGroupId id; +#ifdef DEBUG_ID_DIALOG + std::cerr << "Got selectionChanged signal. Old selection is: " << std::endl; + for(auto i:old_sel.indexes()) std::cerr << " " << i << std::endl; + std::cerr << "Got selectionChanged signal. New selection is: " << std::endl; + for(auto i:new_sel.indexes()) std::cerr << " " << i << std::endl; +#endif - if (item) { - id = RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString()); - } + auto id = RsGxsGroupId(getSelectedIdentity()); - if (id != mId) { +#ifdef DEBUG_ID_DIALOG + std::cerr << "updating selection to id " << id << std::endl; +#endif + if(id != mId) + { mId = id; updateIdentity(); - //updateRepList(); } } - +void IdDialog::updateIdListRequest() +{ + if(updateIdTimer.isActive()) + { + std::cerr << "updateIdListRequest(): restarting timer"<< std::endl; + updateIdTimer.stop(); + updateIdTimer.start(1000); + } + else + { + std::cerr << "updateIdListRequest(): starting timer"<< std::endl; + updateIdTimer.start(1000); + } +} void IdDialog::updateIdList() { - //int accept = filter; + //print_stacktrace(); - RsThread::async([this]() - { - // 1 - get message data from p3GxsForums + RsThread::async([this]() + { + std::list *ids = new std::list(); -#ifdef DEBUG_FORUMS - std::cerr << "Retrieving post data for post " << mThreadId << std::endl; -#endif + if(!rsIdentity->getIdentitiesSummaries(*ids)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve identity metadata." << std::endl; + return; + } - std::list identity_metas ; + RsQThreadUtils::postToObject( [ids,this]() + { - if (!rsIdentity->getIdentitiesSummaries(identity_metas)) - { - std::cerr << "IdDialog::insertIdList() Error getting GroupData" << std::endl; - return; - } + std::cerr << "Updating identity list in widget." << std::endl; - std::set ids; - for(auto it(identity_metas.begin());it!=identity_metas.end();++it) - ids.insert(RsGxsId((*it).mGroupId)); - - std::vector groups; - - if(!rsIdentity->getIdentitiesInfo(ids,groups)) - { - std::cerr << "IdDialog::insertIdList() Error getting identities info" << std::endl; - return; - } - - auto ids_set = new std::map(); - - for(auto it(groups.begin()); it!=groups.end(); ++it) - (*ids_set)[(*it).mMeta.mGroupId] = *it; - - RsQThreadUtils::postToObject( [ids_set, this] () - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - loadIdentities(*ids_set); - delete ids_set; - - }, this ); + applyWhileKeepingTree( [ids,this]() + { + std::cerr << "setting new identity in model." << std::endl; + mIdListModel->setIdentities(*ids) ; + delete ids; + ui->label_count->setText("("+QString::number(mIdListModel->count())+")"); + }); + }); }); } +#ifdef TO_REMOVE bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept) { bool isLinkedToOwnNode = (data.mPgpKnown && (data.mPgpId == ownPgpId)) ; @@ -1476,13 +1560,13 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, rsPeers->getGPGDetails(data.mPgpId, details); item->setText(RSID_COL_IDTYPE, QString::fromUtf8(details.name.c_str())); item->setToolTip(RSID_COL_IDTYPE,"Verified signature from node "+QString::fromStdString(data.mPgpId.toStdString())) ; - - + + QString tooltip = tr("Node name:")+" " + QString::fromUtf8(details.name.c_str()) + "\n"; tooltip += tr("Node Id :")+" " + QString::fromStdString(data.mPgpId.toStdString()) ; item->setToolTip(RSID_COL_KEYID,tooltip) ; } - else + else { QString txt = tr("[Unknown node]"); item->setText(RSID_COL_IDTYPE, txt); @@ -1508,112 +1592,7 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, return true; } -void IdDialog::loadIdentities(const std::map& ids_set_const) -{ - auto ids_set(ids_set_const); - - //First: Get current item to restore after - RsGxsGroupId oldCurrentId = mIdToNavigate; - { - QTreeWidgetItem *oldCurrent = ui->idTreeWidget->currentItem(); - if (oldCurrent) { - oldCurrentId = RsGxsGroupId(oldCurrent->text(RSID_COL_KEYID).toStdString()); - } - } - - //Save expanding - Settings->beginGroup("IdDialog"); - Settings->setValue("ExpandAll", allItem->isExpanded()); - Settings->setValue("ExpandContacts", contactsItem->isExpanded()); - Settings->setValue("ExpandOwn", ownItem->isExpanded()); - Settings->endGroup(); - - - int accept = filter; - - mStateHelper->setActive(IDDIALOG_IDLIST, true); - - RsPgpId ownPgpId = rsPeers->getGPGOwnId(); - - // Update existing and remove not existing items - // Also remove items that do not have the correct parent - - QTreeWidgetItemIterator itemIterator(ui->idTreeWidget); - QTreeWidgetItem *item = NULL; - - while ((item = *itemIterator) != NULL) - { - ++itemIterator; - auto it = ids_set.find(RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString())) ; - - if(it == ids_set.end()) - { - if(item != allItem && item != contactsItem && item != ownItem) - delete(item); - - continue ; - } - - QTreeWidgetItem *parent_item = item->parent() ; - -// if(it->second.mMeta.mPublishTs > time(NULL) - 20 || it->second.mMeta.mGroupId == RsGxsGroupId("3de2172503675206b3a23c997e5ee688")) -// std::cerr << "Captured ID " <second.mMeta.mGroupId << std::endl; - - if( (parent_item == allItem && it->second.mIsAContact) || (parent_item == contactsItem && !it->second.mIsAContact)) - { - delete item ; // do not remove from the list, so that it is added again in the correct place. - continue ; - } - - if (!fillIdListItem(it->second, item, ownPgpId, accept)) - delete(item); - - ids_set.erase(it); // erase, so it is not considered to be a new item - } - - /* Insert new items */ - for (std::map::const_iterator vit = ids_set.begin(); vit != ids_set.end(); ++vit) - { - RsGxsIdGroup data = vit->second ; - - item = NULL; - - if (fillIdListItem(data, item, ownPgpId, accept)) - { - if(data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - ownItem->addChild(item); - else if(data.mIsAContact) - contactsItem->addChild(item); - else - allItem->addChild(item); - - } - } - - /* count items */ - int itemCount = contactsItem->childCount() + allItem->childCount() + ownItem->childCount(); - ui->label_count->setText( "(" + QString::number( itemCount ) + ")" ); - - int contactsCount = contactsItem->childCount() ; - int allCount = allItem->childCount() ; - int ownCount = ownItem->childCount(); - - contactsItem->setText(0, tr("My contacts") + " (" + QString::number( contactsCount ) + ")" ); - allItem->setText(0, tr("All") + " (" + QString::number( allCount ) + ")" ); - ownItem->setText(0, tr("My own identities") + " (" + QString::number( ownCount ) + ")" ); - - - //Restore expanding - Settings->beginGroup("IdDialog"); - allItem->setExpanded(Settings->value("ExpandAll", QVariant(true)).toBool()); - ownItem->setExpanded(Settings->value("ExpandOwn", QVariant(true)).toBool()); - contactsItem->setExpanded(Settings->value("ExpandContacts", QVariant(true)).toBool()); - Settings->endGroup(); - - navigate(RsGxsId(oldCurrentId)); - filterIds(); - updateSelection(); -} +#endif void IdDialog::updateIdentity() { @@ -1659,7 +1638,7 @@ void IdDialog::updateIdentity() loadIdentity(group); - }, this ); + }, this ); }); } @@ -1675,7 +1654,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) RsPgpId ownPgpId = rsPeers->getGPGOwnId(); ui->lineEdit_PublishTS->setText(QDateTime::fromMSecsSinceEpoch(qint64(1000)*data.mMeta.mPublishTs).toString(Qt::SystemLocaleShortDate)); - ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); + //ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE)); ui->lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId.toStdString())); //ui->lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash.toStdString())); if(data.mPgpKnown) @@ -1731,7 +1710,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) ui->lineEdit_GpgId->show() ; ui->label_GpgId->show() ; } - + if(data.mPgpKnown) { ui->lineEdit_GpgName->show() ; @@ -1771,7 +1750,6 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) if (isOwnId) { - mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, false); mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, false); // ui->editIdentity->setEnabled(true); // ui->removeIdentity->setEnabled(true); @@ -1781,8 +1759,6 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) } else { - // No Reputation yet! - mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, true); mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, true); // ui->editIdentity->setEnabled(false); // ui->removeIdentity->setEnabled(false); @@ -1826,7 +1802,7 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) frep_string = tr("No votes from friends") ; ui->neighborNodesOpinion_TF->setText(frep_string) ; - + ui->label_positive->setText(QString::number(info.mFriendsPositiveVotes)); ui->label_negative->setText(QString::number(info.mFriendsNegativeVotes)); @@ -1849,9 +1825,9 @@ void IdDialog::loadIdentity(RsGxsIdGroup data) switch(info.mOwnOpinion) { - case RsOpinion::NEGATIVE: ui->ownOpinion_CB->setCurrentIndex(0); break; - case RsOpinion::NEUTRAL : ui->ownOpinion_CB->setCurrentIndex(1); break; - case RsOpinion::POSITIVE: ui->ownOpinion_CB->setCurrentIndex(2); break; + case RsOpinion::NEGATIVE: whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(0); break; + case RsOpinion::NEUTRAL : whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(1); break; + case RsOpinion::POSITIVE: whileBlocking(ui->ownOpinion_CB)->setCurrentIndex(2); break; default: std::cerr << "Unexpected value in own opinion: " << static_cast(info.mOwnOpinion) << std::endl; @@ -2023,33 +1999,62 @@ void IdDialog::modifyReputation() // trigger refresh when finished. // basic / anstype are not needed. - updateIdentity(); - updateIdList(); + //updateIdentity(); + //updateIdList(); return; } - + void IdDialog::navigate(const RsGxsId& gxs_id) { -#ifdef ID_DEBUG + mIdListModel->debug_dump(); +#ifndef ID_DEBUG std::cerr << "IdDialog::navigate to " << gxs_id.toStdString() << std::endl; #endif + if(gxs_id.isNull()) + return; + + auto indx = mIdListModel->getIndexOfIdentity(gxs_id); + + if(!indx.isValid()) + { + RsErr() << "Invalid index found for identity " << gxs_id << std::endl; + return; + } + std::cerr << "Obtained index " << indx << ": id of that index is " << mIdListModel->getIdentity(indx) << std::endl; + + QModelIndex proxy_indx = mProxyModel->mapFromSource(indx); + + std::cerr << "Obtained proxy index " << proxy_indx << std::endl; + // in order to do this, we just select the correct ID in the ID list - if (!gxs_id.isNull()) - { - QList select = ui->idTreeWidget->findItems(QString::fromStdString(gxs_id.toStdString()),Qt::MatchExactly | Qt::MatchRecursive | Qt::MatchWrap,RSID_COL_KEYID) ; + Q_ASSERT(ui->idTreeWidget->model() == mProxyModel); - if(select.empty()) - { - mIdToNavigate = RsGxsGroupId(gxs_id); - std::cerr << "Cannot find item with ID " << gxs_id << " in ID list." << std::endl; - return; - } - ui->idTreeWidget->setCurrentItem(*select.begin(),true); - } + if(!proxy_indx.isValid()) + { + std::cerr << "Cannot find item with ID " << gxs_id << " in ID list." << std::endl; + return; + } + std::cerr << "Row hidden? " << ui->idTreeWidget->isRowHidden(proxy_indx.row(),proxy_indx.parent()) << std::endl; - mIdToNavigate = RsGxsGroupId(); + { + auto ii = mProxyModel->mapToSource(proxy_indx); + std::cerr << "Remapping index to source: " << ii << std::endl; + } + ui->idTreeWidget->selectionModel()->select(proxy_indx,QItemSelectionModel::Current|QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + { + auto lst = ui->idTreeWidget->selectionModel()->selectedIndexes(); + std::cerr << "Just after calling select(), the selected index list has size " << lst.size() << std::endl; + } + ui->idTreeWidget->scrollTo(proxy_indx);//May change if model reloaded + ui->idTreeWidget->setFocus(); + + // This has to be done manually because for some reason the proxy model doesn't work with the selection model + // No signal is emitted when calling setCurrentIndex() above. + + //mId = RsGxsGroupId(gxs_id); + //updateIdentity(); } void IdDialog::updateDisplay(bool complete) @@ -2067,6 +2072,49 @@ void IdDialog::updateDisplay(bool complete) } } +std::list IdDialog::getSelectedIdentities() const +{ + QModelIndexList selectedIndexes_proxy = ui->idTreeWidget->selectionModel()->selectedIndexes(); + std::list res; + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Parsing selected index list: " << std::endl; +#endif + for(auto indx_proxy:selectedIndexes_proxy) + { + RsGxsId id; + + if(indx_proxy.column() == RsIdentityListModel::COLUMN_THREAD_ID) // this removes duplicates + { + auto indx = mProxyModel->mapToSource(indx_proxy); + auto id = mIdListModel->getIdentity(indx); + +#ifdef DEBUG_ID_DIALOG + std::cerr << " indx: " << indx_proxy << " original indx: " << indx << " identity: " << id << std::endl; +#endif + + if( !id.isNull() ) + res.push_back(id); + } + } + + return res; +} + +RsGxsId IdDialog::getSelectedIdentity() const +{ + auto lst = getSelectedIdentities(); + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Selected identities has size " << lst.size() << std::endl; +#endif + + if(lst.size() != 1) + return RsGxsId(); + else + return lst.front(); +} + void IdDialog::addIdentity() { IdEditDialog dlg(this); @@ -2076,240 +2124,248 @@ void IdDialog::addIdentity() void IdDialog::removeIdentity() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { -#ifdef ID_DEBUG - std::cerr << "IdDialog::editIdentity() Invalid item"; - std::cerr << std::endl; -#endif - return; - } + RsGxsId id = getSelectedIdentity(); - if ((QMessageBox::question(this, tr("Really delete?"), tr("Do you really want to delete this identity?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No))== QMessageBox::Yes) - { - std::string keyId = item->text(RSID_COL_KEYID).toStdString(); + if(id.isNull()) + return; - uint32_t dummyToken = 0; - RsGxsIdGroup group; - group.mMeta.mGroupId=RsGxsGroupId(keyId); - rsIdentity->deleteIdentity(dummyToken, group); - } + if ((QMessageBox::question(this, tr("Really delete?"), tr("Do you really want to delete this identity?\nThis cannot be undone."), QMessageBox::Yes|QMessageBox::No, QMessageBox::No))== QMessageBox::Yes) + rsIdentity->deleteIdentity(id); } void IdDialog::editIdentity() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { -#ifdef ID_DEBUG - std::cerr << "IdDialog::editIdentity() Invalid item"; - std::cerr << std::endl; -#endif - return; - } + RsGxsId id = getSelectedIdentity(); - RsGxsGroupId keyId = RsGxsGroupId(item->text(RSID_COL_KEYID).toStdString()); - if (keyId.isNull()) { - return; - } + if(id.isNull()) + return; - IdEditDialog dlg(this); - dlg.setupExistingId(keyId); - dlg.exec(); + IdEditDialog dlg(this); + dlg.setupExistingId(RsGxsGroupId(id)); + dlg.exec(); } void IdDialog::filterIds() { - int filterColumn = ui->filterLineEdit->currentFilter(); QString text = ui->filterLineEdit->text(); - ui->idTreeWidget->filterItems(filterColumn, text); + int8_t ft=0; + + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_ID)) ft |= RsIdentityListModel::FILTER_TYPE_ID; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_NAME)) ft |= RsIdentityListModel::FILTER_TYPE_NAME; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_NAME)) ft |= RsIdentityListModel::FILTER_TYPE_OWNER_NAME; + if(!ui->idTreeWidget->isColumnHidden(RsIdentityListModel::COLUMN_THREAD_OWNER_ID)) ft |= RsIdentityListModel::FILTER_TYPE_OWNER_ID; + + mIdListModel->setFilter(ft,{ text }); } +void IdDialog::headerContextMenuRequested(QPoint) +{ + QMenu displayMenu(this); + + // create menu header + //QHBoxLayout *hbox = new QHBoxLayout(widget); + //hbox->setMargin(0); + //hbox->setSpacing(6); + + auto addEntry = [&](const QString& name,RsIdentityListModel::Columns col) + { + QAction *action = displayMenu.addAction(QIcon(), name, this, SLOT(toggleColumnVisible())); + action->setCheckable(true); + action->setData(static_cast(col)); + action->setChecked(!ui->idTreeWidget->header()->isSectionHidden(col)); + }; + + addEntry(tr("Id"),RsIdentityListModel::COLUMN_THREAD_ID); + addEntry(tr("Owner Id"),RsIdentityListModel::COLUMN_THREAD_OWNER_ID); + addEntry(tr("Owner Name"),RsIdentityListModel::COLUMN_THREAD_OWNER_NAME); + addEntry(tr("Reputation"),RsIdentityListModel::COLUMN_THREAD_REPUTATION); + + //addEntry(tr("Name"),RsIdentityListModel::COLUMN_THREAD_NAME); + + displayMenu.exec(QCursor::pos()); +} + +void IdDialog::toggleColumnVisible() +{ + QAction *action = dynamic_cast(sender()); + + std::cerr << "Aciton = " << (void*)action << std::endl; + if (!action) + return; + + int column = action->data().toInt(); + bool visible = action->isChecked(); + + ui->idTreeWidget->setColumnHidden(column, !visible); +} void IdDialog::IdListCustomPopupMenu( QPoint ) { - QMenu *contextMenu = new QMenu(this); + QMenu contextMenu(this); + std::list own_identities; + rsIdentity->getOwnIds(own_identities); - std::list own_identities; - rsIdentity->getOwnIds(own_identities); + // make some stats about what's selected. If the same value is used for all selected items, it can be switched. - // make some stats about what's selected. If the same value is used for all selected items, it can be switched. + auto lst = getSelectedIdentities(); - QList selected_items = ui->idTreeWidget->selectedItems(); + if(lst.empty()) + return ; - bool root_node_present = false ; - bool one_item_owned_by_you = false ; - uint32_t n_positive_reputations = 0 ; - uint32_t n_negative_reputations = 0 ; - uint32_t n_neutral_reputations = 0 ; - uint32_t n_is_a_contact = 0 ; - uint32_t n_is_not_a_contact = 0 ; - uint32_t n_selected_items =0 ; + //bool root_node_present = false ; + bool one_item_owned_by_you = false ; + uint32_t n_positive_reputations = 0 ; + uint32_t n_negative_reputations = 0 ; + uint32_t n_neutral_reputations = 0 ; + uint32_t n_is_a_contact = 0 ; + uint32_t n_is_not_a_contact = 0 ; + uint32_t n_selected_items =0 ; - for(auto& it :selected_items) - { - if(it == allItem || it == contactsItem || it == ownItem) - { - root_node_present = true ; - continue ; - } + for(auto& keyId :lst) + { + //if(it == allItem || it == contactsItem || it == ownItem) + //{ + // root_node_present = true ; + // continue ; + //} - uint32_t item_flags = it->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ; + //uint32_t item_flags = mIdListModel->data(RSID_COL_KEYID,Qt::UserRole).toUInt() ; - if(item_flags & RSID_FILTER_OWNED_BY_YOU) - one_item_owned_by_you = true ; + if(rsIdentity->isOwnId(keyId)) + one_item_owned_by_you = true ; #ifdef ID_DEBUG - std::cerr << " item flags = " << item_flags << std::endl; + std::cerr << " item flags = " << item_flags << std::endl; #endif - RsGxsId keyId(it->text(RSID_COL_KEYID).toStdString()); + RsIdentityDetails det ; + rsIdentity->getIdDetails(keyId,det) ; - RsIdentityDetails det ; - rsIdentity->getIdDetails(keyId,det) ; + switch(det.mReputation.mOwnOpinion) + { + case RsOpinion::NEGATIVE: ++n_negative_reputations; break; + case RsOpinion::POSITIVE: ++n_positive_reputations; break; + case RsOpinion::NEUTRAL: ++n_neutral_reputations; break; + } - switch(det.mReputation.mOwnOpinion) - { - case RsOpinion::NEGATIVE: ++n_negative_reputations; break; - case RsOpinion::POSITIVE: ++n_positive_reputations; break; - case RsOpinion::NEUTRAL: ++n_neutral_reputations; break; - } + ++n_selected_items; - ++n_selected_items; + if(rsIdentity->isARegularContact(keyId)) + ++n_is_a_contact ; + else + ++n_is_not_a_contact ; + } - if(rsIdentity->isARegularContact(keyId)) - ++n_is_a_contact ; - else - ++n_is_not_a_contact ; - } + if(!one_item_owned_by_you) + { + QFrame *widget = new QFrame(&contextMenu); + widget->setObjectName("gradFrame"); //Use qss + //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); - if(!root_node_present) // don't show menu if some of the root nodes are present - { + // create menu header + QHBoxLayout *hbox = new QHBoxLayout(widget); + hbox->setMargin(0); + hbox->setSpacing(6); - if(!one_item_owned_by_you) - { - QFrame *widget = new QFrame(contextMenu); - widget->setObjectName("gradFrame"); //Use qss - //widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + QLabel *iconLabel = new QLabel(widget); + iconLabel->setObjectName("trans_Icon"); + QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); + iconLabel->setPixmap(pix); + iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); + hbox->addWidget(iconLabel); - // create menu header - QHBoxLayout *hbox = new QHBoxLayout(widget); - hbox->setMargin(0); - hbox->setSpacing(6); + QLabel *textLabel = new QLabel("" + ui->titleBarLabel->text() + "", widget); + textLabel->setObjectName("trans_Text"); + hbox->addWidget(textLabel); - QLabel *iconLabel = new QLabel(widget); - iconLabel->setObjectName("trans_Icon"); - QPixmap pix = FilesDefs::getPixmapFromQtResourcePath(":/images/user/friends24.png").scaledToHeight(QFontMetricsF(iconLabel->font()).height()*1.5); - iconLabel->setPixmap(pix); - iconLabel->setMaximumSize(iconLabel->frameSize().height() + pix.height(), pix.width()); - hbox->addWidget(iconLabel); + QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(spacerItem); - QLabel *textLabel = new QLabel("" + ui->titleBarLabel->text() + "", widget); - textLabel->setObjectName("trans_Text"); - hbox->addWidget(textLabel); + widget->setLayout(hbox); - QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - hbox->addItem(spacerItem); + QWidgetAction *widgetAction = new QWidgetAction(this); + widgetAction->setDefaultWidget(widget); + contextMenu.addAction(widgetAction); - widget->setLayout(hbox); + if(n_selected_items == 1) // if only one item is selected, allow to chat with this item + { + if(own_identities.size() <= 1) + { + QAction *action = contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); - QWidgetAction *widgetAction = new QWidgetAction(this); - widgetAction->setDefaultWidget(widget); - contextMenu->addAction(widgetAction); + if(own_identities.empty()) + action->setEnabled(false) ; + else + action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; + } + else + { + QMenu *mnu = contextMenu.addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"),tr("Chat with this person as...")) ; - if(n_selected_items == 1) // if only one item is selected, allow to chat with this item - { - if(own_identities.size() <= 1) - { - QAction *action = contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"), tr("Chat with this person"), this, SLOT(chatIdentity())); + for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) + { + RsIdentityDetails idd ; + rsIdentity->getIdDetails(*it,idd) ; - if(own_identities.empty()) - action->setEnabled(false) ; - else - action->setData(QString::fromStdString((own_identities.front()).toStdString())) ; - } - else - { - QMenu *mnu = contextMenu->addMenu(FilesDefs::getIconFromQtResourcePath(":/icons/png/chats.png"),tr("Chat with this person as...")) ; + QPixmap pixmap ; - for(std::list::const_iterator it=own_identities.begin();it!=own_identities.end();++it) - { - RsIdentityDetails idd ; - rsIdentity->getIdDetails(*it,idd) ; + if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) + pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ; - QPixmap pixmap ; + QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity())); + action->setData(QString::fromStdString((*it).toStdString())) ; + } + } + } + // always allow to send messages + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMsg())); - if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL)) - pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ; + contextMenu.addSeparator(); - QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity())); - action->setData(QString::fromStdString((*it).toStdString())) ; - } - } - } - // always allow to send messages - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/mail/write-mail.png"), tr("Send message"), this, SLOT(sendMsg())); + if(n_is_a_contact == 0) + contextMenu.addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts())); - contextMenu->addSeparator(); + if(n_is_not_a_contact == 0) + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"), tr("Remove from Contacts"), this, SLOT(removefromContacts())); + } + if (n_selected_items==1) + contextMenu.addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; - if(n_is_a_contact == 0) - contextMenu->addAction(QIcon(), tr("Add to Contacts"), this, SLOT(addtoContacts())); + contextMenu.addSeparator(); - if (n_selected_items==1) - contextMenu->addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; + if(n_positive_reputations == 0) // only unban when all items are banned + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson())); - if(n_is_not_a_contact == 0) - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"), tr("Remove from Contacts"), this, SLOT(removefromContacts())); + if(n_neutral_reputations == 0) // only unban when all items are banned + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson())); - contextMenu->addSeparator(); + if(n_negative_reputations == 0) + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson())); - if(n_positive_reputations == 0) // only unban when all items are banned - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-up.png"), tr("Set positive opinion"), this, SLOT(positivePerson())); + if(one_item_owned_by_you && n_selected_items==1) + { + contextMenu.addSeparator(); - if(n_neutral_reputations == 0) // only unban when all items are banned - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-neutral.png"), tr("Set neutral opinion"), this, SLOT(neutralPerson())); + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_EDIT),tr("Edit identity"),this,SLOT(editIdentity())) ; + contextMenu.addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"),tr("Delete identity"),this,SLOT(removeIdentity())) ; + } - if(n_negative_reputations == 0) - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/png/thumbs-down.png"), tr("Set negative opinion"), this, SLOT(negativePerson())); - } + //contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu); - if(one_item_owned_by_you && n_selected_items==1) - { - contextMenu->addSeparator(); - - contextMenu->addAction(QIcon(""),tr("Copy identity to clipboard"),this,SLOT(copyRetroshareLink())) ; - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_EDIT),tr("Edit identity"),this,SLOT(editIdentity())) ; - contextMenu->addAction(FilesDefs::getIconFromQtResourcePath(":/icons/cancel.svg"),tr("Delete identity"),this,SLOT(removeIdentity())) ; - } - - } - - contextMenu = ui->idTreeWidget->createStandardContextMenu(contextMenu); - - contextMenu->exec(QCursor::pos()); - delete contextMenu; + contextMenu.exec(QCursor::pos()); } void IdDialog::copyRetroshareLink() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); + auto gxs_id = getSelectedIdentity(); - if (!item) + if (gxs_id.isNull()) { std::cerr << "IdDialog::editIdentity() Invalid item"; std::cerr << std::endl; return; } - RsGxsId gxs_id(item->text(RSID_COL_KEYID).toStdString()); - - if(gxs_id.isNull()) - { - std::cerr << "Null GXS id. Something went wrong." << std::endl; - return ; - } - RsIdentityDetails details ; if(! rsIdentity->getIdDetails(gxs_id,details)) @@ -2347,35 +2403,33 @@ void IdDialog::copyRetroshareLink() }); } -void IdDialog::chatIdentity() +void IdDialog::chatIdentityItem(const QModelIndex& indx) { - QTreeWidgetItem* item = ui->idTreeWidget->currentItem(); - if (!item) - { - std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item!" << std::endl; - return; - } + auto toGxsId = mIdListModel->getIdentity(indx); - chatIdentityItem(item); -} - -void IdDialog::chatIdentityItem(QTreeWidgetItem* item) -{ - if(!item) + if(toGxsId.isNull()) { std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item." << std::endl; return; } + chatIdentity(toGxsId); +} - std::string&& toIdString(item->text(RSID_COL_KEYID).toStdString()); - RsGxsId toGxsId(toIdString); - if(toGxsId.isNull()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid destination id: " - << toIdString << std::endl; - return; - } +void IdDialog::chatIdentity() +{ + auto id = getSelectedIdentity(); + if(id.isNull()) + { + std::cerr << __PRETTY_FUNCTION__ << " Error. Invalid item!" << std::endl; + return; + } + + chatIdentity(id); +} + +void IdDialog::chatIdentity(const RsGxsId& toGxsId) +{ RsGxsId fromGxsId; QAction* action = qobject_cast(QObject::sender()); if(!action) @@ -2394,8 +2448,7 @@ void IdDialog::chatIdentityItem(QTreeWidgetItem* item) if(fromGxsId.isNull()) { - std::cerr << __PRETTY_FUNCTION__ << " Error. Could not determine sender" - << " identity to open chat toward: " << toIdString << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " Error. Could not determine sender identity to open chat toward: " << toGxsId << std::endl; return; } @@ -2412,12 +2465,12 @@ void IdDialog::chatIdentityItem(QTreeWidgetItem* item) void IdDialog::sendMsg() { - QList selected_items = ui->idTreeWidget->selectedItems(); + auto lst = getSelectedIdentities(); - if(selected_items.empty()) + if(lst.empty()) return ; - if(selected_items.size() > 20) + if(lst.size() > 20) if(QMessageBox::warning(nullptr,tr("Too many identities"),tr("

It is not recommended to send a message to more than 20 persons at once. Large scale diffusion of data (including friend invitations) are much more efficiently handled by forums. Click ok to proceed anyway.

"),QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Cancel)==QMessageBox::Cancel) return; @@ -2425,15 +2478,10 @@ void IdDialog::sendMsg() if (nMsgDialog == NULL) return; - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + for(const auto& id : lst) + nMsgDialog->addRecipient(MessageComposer::TO, id); - std::string keyId = item->text(RSID_COL_KEYID).toStdString(); - - nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(keyId)); - } - nMsgDialog->show(); + nMsgDialog->show(); nMsgDialog->activateWindow(); /* window will destroy itself! */ @@ -2446,14 +2494,11 @@ QString IdDialog::inviteMessage() void IdDialog::sendInvite() { - QTreeWidgetItem *item = ui->idTreeWidget->currentItem(); - if (!item) - { - return; - } + auto id = getSelectedIdentity(); + + if(id.isNull()) + return; - RsGxsId id(ui->lineEdit_KeyId->text().toStdString()); - //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want send a invite with your Certificate?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) { MessageComposer::sendInvite(id,false); @@ -2461,83 +2506,60 @@ void IdDialog::sendInvite() ui->info_Frame_Invite->show(); ui->inviteButton->setEnabled(false); } - + } void IdDialog::negativePerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::NEGATIVE); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::NEGATIVE); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::neutralPerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::NEUTRAL); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::NEUTRAL); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::positivePerson() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; + auto lst = getSelectedIdentities(); - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + for(const auto& id : lst) + rsReputations->setOwnOpinion(id, RsOpinion::POSITIVE); - rsReputations->setOwnOpinion(RsGxsId(Id), RsOpinion::POSITIVE); - } - - updateIdentity(); - updateIdList(); + updateIdentity(); + updateIdListRequest(); } void IdDialog::addtoContacts() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + auto lst = getSelectedIdentities(); - rsIdentity->setAsRegularContact(RsGxsId(Id),true); - } + for(const auto& id : lst) + rsIdentity->setAsRegularContact(id,true); - updateIdList(); + updateIdListRequest(); } void IdDialog::removefromContacts() { - QList selected_items = ui->idTreeWidget->selectedItems(); - for(auto& it : selected_items) - { - QTreeWidgetItem *item = it ; - std::string Id = item->text(RSID_COL_KEYID).toStdString(); + auto lst = getSelectedIdentities(); - rsIdentity->setAsRegularContact(RsGxsId(Id),false); - } + for(const auto& id : lst) + rsIdentity->setAsRegularContact(id,false); - updateIdList(); + updateIdListRequest(); } void IdDialog::on_closeInfoFrameButton_Invite_clicked() @@ -2593,3 +2615,174 @@ void IdDialog::restoreExpandedCircleItems(const std::vector& expanded_root restoreTopLevel(mMyCircleItem,2); } +void IdDialog::applyWhileKeepingTree(std::function predicate) +{ + std::set expanded,selected; + + saveExpandedPathsAndSelection_idTreeView(expanded, selected); +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "After collecting selection, selected paths is: \"" << selected.toStdString() << "\", " ; + std::cerr << "expanded paths are: " << std::endl; + for(auto path:expanded) + std::cerr << " \"" << path.toStdString() << "\"" << std::endl; + std::cerr << "Current sort column is: " << mLastSortColumn << " and order is " << mLastSortOrder << std::endl; +#endif + + // This is a hack to avoid crashes on windows while calling endInsertRows(). I'm not sure wether these crashes are + // due to a Qt bug, or a misuse of the proxy model on my side. Anyway, this solves them for good. + // As a side effect we need to save/restore hidden columns because setSourceModel() resets this setting. + + // save hidden columns and sizes + std::vector col_visible(RsIdentityListModel::COLUMN_THREAD_NB_COLUMNS); + std::vector col_sizes(RsIdentityListModel::COLUMN_THREAD_NB_COLUMNS); + + for(int i=0;iidTreeWidget->isColumnHidden(i); + col_sizes[i] = ui->idTreeWidget->columnWidth(i); + } + +#ifdef SUSPENDED +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Applying predicate..." << std::endl; +#endif +#endif + mProxyModel->setSourceModel(nullptr); + predicate(); + mProxyModel->setSourceModel(mIdListModel); + + restoreExpandedPathsAndSelection_idTreeView(expanded,selected); + // restore hidden columns + for(uint32_t i=0;iidTreeWidget->setColumnHidden(i,!col_visible[i]); + ui->idTreeWidget->setColumnWidth(i,col_sizes[i]); + } + + mProxyModel->setSortingEnabled(true); + mProxyModel->sort(mLastSortColumn,mLastSortOrder); + mProxyModel->setSortingEnabled(false); +#ifdef SUSPENDED + // restore sorting + // sortColumn(mLastSortColumn,mLastSortOrder); +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Sorting again with sort column: " << mLastSortColumn << " and order " << mLastSortOrder << std::endl; +#endif + +// if(selected_index.isValid()) +// ui->idTreeWidget->scrollTo(selected_index); +#endif +} + +void IdDialog::saveExpandedPathsAndSelection_idTreeView(std::set& expanded, std::set& selected) +{ +#ifdef DEBUG_ID_DIALOG + std::cerr << "Saving expended paths and selection..." << std::endl; +#endif + + for(int row = 0; row < mProxyModel->rowCount(); ++row) + recursSaveExpandedItems_idTreeView(mProxyModel->index(row,0),QStringList(),expanded,selected); +} + +void IdDialog::restoreExpandedPathsAndSelection_idTreeView(const std::set& expanded, const std::set& selected) +{ +#ifdef DEBUG_ID_DIALOG + std::cerr << "Restoring expanded paths and selection..." << std::endl; + std::cerr << " expanded: " << expanded.size() << " items" << std::endl; + std::cerr << " selected: " << selected.size() << " items" << std::endl; +#endif + ui->idTreeWidget->blockSignals(true) ; + ui->idTreeWidget->selectionModel()->blockSignals(true) ; + + ui->idTreeWidget->clearSelection(); + + for(int row = 0; row < mProxyModel->rowCount(); ++row) + recursRestoreExpandedItems_idTreeView(mProxyModel->index(row,0),QStringList(),expanded,selected); + + ui->idTreeWidget->selectionModel()->blockSignals(false) ; + ui->idTreeWidget->blockSignals(false) ; +} + +void IdDialog::recursSaveExpandedItems_idTreeView(const QModelIndex& proxy_index,const QStringList& parent_path,std::set& expanded,std::set& selected) +{ + QStringList local_path = parent_path; + + local_path.push_back(mIdListModel->indexIdentifier(mProxyModel->mapToSource(proxy_index))); + + if(ui->idTreeWidget->isExpanded(proxy_index)) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Adding expanded path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + if(proxy_index.isValid()) + expanded.insert(local_path) ; + + for(int row=0;rowrowCount(proxy_index);++row) + recursSaveExpandedItems_idTreeView(proxy_index.child(row,0),local_path,expanded,selected) ; + } + + if(ui->idTreeWidget->selectionModel()->isSelected(proxy_index)) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Adding selected path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + selected.insert(local_path); + } +} + +void IdDialog::recursRestoreExpandedItems_idTreeView(const QModelIndex& proxy_index,const QStringList& parent_path,const std::set& expanded,const std::set& selected) +{ + QStringList local_path = parent_path; + local_path.push_back(mIdListModel->indexIdentifier(mProxyModel->mapToSource(proxy_index))); + +#ifdef DEBUG_ID_DIALOG + std::cerr << "Local path = " ; for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + + if(expanded.find(local_path) != expanded.end()) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << " re expanding " ; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + + ui->idTreeWidget->setExpanded(proxy_index,true) ; + + for(int row=0;rowrowCount(proxy_index);++row) + recursRestoreExpandedItems_idTreeView(proxy_index.child(row,0),local_path,expanded,selected) ; + } + + if(selected.find(local_path) != selected.end()) + { +#ifdef DEBUG_ID_DIALOG + std::cerr << "Restoring selected path "; + for(auto L:local_path) std::cerr << "\"" << L.toStdString() << "\" " ; std::cerr << std::endl; +#endif + ui->idTreeWidget->selectionModel()->select(proxy_index, QItemSelectionModel::Current|QItemSelectionModel::Select | QItemSelectionModel::Rows); + } +} + +void IdDialog::sortColumn(int col,Qt::SortOrder so) +{ +#ifdef DEBUG_NEW_FRIEND_LIST + std::cerr << "Sorting with column=" << col << " and order=" << so << std::endl; +#endif + std::set expanded_indexes,selected_indexes; + + saveExpandedPathsAndSelection_idTreeView(expanded_indexes, selected_indexes); + whileBlocking(ui->idTreeWidget)->clearSelection(); + + mProxyModel->setSortingEnabled(true); + mProxyModel->sort(col,so); + mProxyModel->setSortingEnabled(false); + + restoreExpandedPathsAndSelection_idTreeView(expanded_indexes,selected_indexes); + + //if(selected_index.isValid()) + // ui->peerTreeWidget->scrollTo(selected_index); + + mLastSortColumn = col; + mLastSortOrder = so; +} diff --git a/retroshare-gui/src/gui/Identity/IdDialog.h b/retroshare-gui/src/gui/Identity/IdDialog.h index 403b3a437..d4629a5af 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.h +++ b/retroshare-gui/src/gui/Identity/IdDialog.h @@ -22,8 +22,10 @@ #define IDENTITYDIALOG_H #include "gui/gxs/RsGxsUpdateBroadcastPage.h" +#include "util/FontSizeHandler.h" -#include +#include "retroshare/rsidentity.h" +#include "IdentityListModel.h" #include @@ -34,7 +36,11 @@ class IdDialog; } class UIStateHelper; +class QStyledItemDelegate; class QTreeWidgetItem; +class RsIdentityListModel; +class IdListSortFilterProxyModel; +class QItemSelection; class IdDialog : public MainPage { @@ -58,6 +64,7 @@ protected: void loadIdentity(RsGxsIdGroup id_data); void loadCircles(const std::list& circle_metas); + void updateIdListRequest(); //void requestCircleGroupData(const RsGxsCircleId& circle_id); bool getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) ; @@ -66,13 +73,13 @@ protected: private slots: - void updateIdList(); - void updateCircles(); - - void createExternalCircle(); + void updateIdList(); + void updateCircles(); + void createExternalCircle(); void showEditExistingCircle(); void updateCirclesDisplay(); void toggleAutoBanIdentities(bool b); + void sortColumn(int col,Qt::SortOrder so); void acceptCircleSubscription() ; void cancelCircleSubscription() ; @@ -86,17 +93,20 @@ private slots: void removeIdentity(); void editIdentity(); void chatIdentity(); - void chatIdentityItem(QTreeWidgetItem* item); - void sendMsg(); + void chatIdentityItem(const QModelIndex &indx); + void chatIdentity(const RsGxsId& toGxsId); + void sendMsg(); void copyRetroshareLink(); void on_closeInfoFrameButton_Invite_clicked(); - void updateSelection(); + void updateSelection(const QItemSelection &new_sel, const QItemSelection &old_sel); void modifyReputation(); /** Create the context popup menu and it's submenus */ void IdListCustomPopupMenu( QPoint point ); + void headerContextMenuRequested(QPoint); + void toggleColumnVisible(); void CircleListCustomPopupMenu(QPoint point) ; #ifdef SUSPENDED @@ -117,7 +127,12 @@ private: void processSettings(bool load); QString createUsageString(const RsIdentityUsage& u) const; - void requestIdData(std::list &ids); + void saveExpandedPathsAndSelection_idTreeView(std::set &expanded, std::set &selected); + void restoreExpandedPathsAndSelection_idTreeView(const std::set& expanded, const std::set& selelected); + void recursSaveExpandedItems_idTreeView(const QModelIndex& index, const QStringList& parent_path, std::set& expanded, std::set& selected); + void recursRestoreExpandedItems_idTreeView(const QModelIndex& index,const QStringList& parent_path,const std::set& expanded,const std::set& selected); + + void requestIdData(std::list &ids); bool fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept); void insertIdList(uint32_t token); void filterIds(); @@ -134,20 +149,32 @@ private: private: UIStateHelper *mStateHelper; - QTreeWidgetItem *contactsItem; - QTreeWidgetItem *allItem; - QTreeWidgetItem *ownItem; QTreeWidgetItem *mExternalBelongingCircleItem; QTreeWidgetItem *mExternalOtherCircleItem; QTreeWidgetItem *mMyCircleItem; RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ; - void saveExpandedCircleItems(std::vector &expanded_root_items, std::set& expanded_circle_items) const; + int mLastSortColumn; + Qt::SortOrder mLastSortOrder; + + void saveExpandedCircleItems(std::vector &expanded_root_items, std::set& expanded_circle_items) const; void restoreExpandedCircleItems(const std::vector& expanded_root_items,const std::set& expanded_circle_items); - RsGxsGroupId mId; + void applyWhileKeepingTree(std::function predicate); + + RsGxsId getSelectedIdentity() const; + std::list getSelectedIdentities() const; + + RsGxsGroupId mId; RsGxsGroupId mIdToNavigate; int filter; + bool mColumnSizeAlreadySet; // remembers if we already did some size set. If not, automatically stretch to content. + + QStyledItemDelegate *mElidedLabelDelegate; + QStyledItemDelegate *mReputationDelegate; + + RsIdentityListModel *mIdListModel; + IdListSortFilterProxyModel *mProxyModel; void handleEvent_main_thread(std::shared_ptr event); RsEventsHandlerId_t mEventHandlerId_identity; @@ -157,6 +184,8 @@ private: bool needUpdateIdsOnNextShow; bool needUpdateCirclesOnNextShow; + FontSizeHandler mFontSizeHandler; + /* UI - Designer */ Ui::IdDialog *ui; }; diff --git a/retroshare-gui/src/gui/Identity/IdDialog.ui b/retroshare-gui/src/gui/Identity/IdDialog.ui index 1c504f8fc..37522524e 100644 --- a/retroshare-gui/src/gui/Identity/IdDialog.ui +++ b/retroshare-gui/src/gui/Identity/IdDialog.ui @@ -127,7 +127,7 @@ Qt::NoFocus - + :/icons/help_64.png:/icons/help_64.png @@ -154,10 +154,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -173,7 +173,11 @@ 1 - + + + Search... + + @@ -211,18 +215,13 @@ - + 0 0 - - - 11 - - Qt::CustomContextMenu @@ -241,39 +240,9 @@ true - - false + + true - - - Persons - - - - - Identity ID - - - - - Owned by - - - - - - - - Votes - - - AlignLeading|AlignVCenter - - - - :/icons/flag-green.png:/icons/flag-green.png - - @@ -301,15 +270,15 @@ 0 0 - 505 - 716 + 535 + 784 - + - 0 + 3 @@ -334,10 +303,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised Your Avatar @@ -478,6 +447,265 @@ + + + + + 22 + + + + People + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 0 + 299 + + + + + + + + 9 + + + + + Auto-Ban all identities signed by the same node + + + Auto-Ban profile + + + + + + + <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> + + + true + + + + + + + Ban-option: + + + + + + + true + + + + + + + true + + + + + + + Identity ID : + + + + + + + Last used: + + + + + + + Qt::Horizontal + + + + + + + Owner node ID : + + + + + + + Created on : + + + + + + + Friend votes: + + + true + + + + + + + Type: + + + + + + + true + + + true + + + + + + + Your opinion: + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + true + + + true + + + + + + + <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> + + + + 22 + 22 + + + + + Negative + + + + :/icons/png/thumbs-down.png:/icons/png/thumbs-down.png + + + + + Neutral + + + + :/icons/png/thumbs-neutral.png:/icons/png/thumbs-neutral.png + + + + + Positive + + + + :/icons/png/thumbs-up.png:/icons/png/thumbs-up.png + + + + + + + + <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> + + + true + + + + + + + Owner node name : + + + + + + + true + + + true + + + + + + + true + + + + + + + + 75 + true + + + + Overall: + + + + + + @@ -690,276 +918,6 @@ border-image: url(:/images/closepressed.png) - - - - - 0 - 0 - - - - - 0 - 299 - - - - Identity info - - - - - - true - - - true - - - - - - - Last used: - - - - - - - Identity name : - - - - - - - Owner node name : - - - - - - - true - - - true - - - - - - - Auto-Ban all identities signed by the same node - - - Auto-Ban profile - - - - - - - true - - - - - - - Your opinion: - - - - - - - true - - - - - - - true - - - - - - - - 75 - true - - - - Overall: - - - - - - - Created on : - - - - - - - Owner node ID : - - - - - - - Ban-option: - - - - - - - <html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html> - - - true - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - Identity ID : - - - - - - - Qt::Horizontal - - - - - - - true - - - true - - - - - - - Type: - - - - - - - <html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html> - - - - 22 - 22 - - - - - Negative - - - - :/icons/png/thumbs-down.png:/icons/png/thumbs-down.png - - - - - Neutral - - - - :/icons/png/thumbs-neutral.png:/icons/png/thumbs-neutral.png - - - - - Positive - - - - :/icons/png/thumbs-up.png:/icons/png/thumbs-up.png - - - - - - - - true - - - true - - - - - - - <html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html> - - - true - - - - - - - Friend votes: - - - true - - - - - - - - - - - 22 - - - - People - - - @@ -1029,11 +987,6 @@ border-image: url(:/images/closepressed.png)
- - - 11 - - Qt::CustomContextMenu @@ -1094,23 +1047,19 @@ border-image: url(:/images/closepressed.png) LineEditClear QLineEdit -
gui/common/LineEditClear.h
-
- - RSTreeWidget - QTreeWidget -
gui/common/RSTreeWidget.h
-
- - ElidedLabel - QLabel -
gui/common/ElidedLabel.h
+
gui/common/LineEditClear.h
RSComboBox QComboBox
gui/common/RSComboBox.h
+ + ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
RSTextBrowser QTextBrowser @@ -1121,8 +1070,8 @@ border-image: url(:/images/closepressed.png) idTreeWidget - + diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.cpp b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp new file mode 100644 index 000000000..b55d9c160 --- /dev/null +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp @@ -0,0 +1,968 @@ +/******************************************************************************* + * retroshare-gui/src/gui/msgs/RsFriendListModel.cpp * + * * + * Copyright 2019 by Cyril Soler * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gui/common/AvatarDefs.h" +#include "util/qtthreadsutils.h" +#include "util/HandleRichText.h" +#include "util/DateTime.h" +#include "gui/gxs/GxsIdDetails.h" +#include "retroshare/rsexpr.h" + +#include "IdentityListModel.h" + +//#define DEBUG_MODEL +//#define DEBUG_MODEL_INDEX + +std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere + +const QString RsIdentityListModel::FilterString("filtered"); + +const uint32_t MAX_INTERNAL_DATA_UPDATE_DELAY = 300 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes. +const uint32_t MAX_NODE_UPDATE_DELAY = 10 ; // re-update the internal data every 5 mins. Should properly cover sleep/wake-up changes. + +static const uint32_t ID_DETAILS_UPDATE_DELAY = 5; // update each node every 5 secs. + +RsIdentityListModel::RsIdentityListModel(QObject *parent) + : QAbstractItemModel(parent) + , mLastInternalDataUpdate(0), mLastNodeUpdate(0) +{ + mFontSize = QApplication::font().pointSize(); + + mFilterStrings.clear(); + mIdentityUpdateTimer = new QTimer(); + connect(mIdentityUpdateTimer,SIGNAL(timeout()),this,SLOT(timerUpdate())); +} + +void RsIdentityListModel::timerUpdate() +{ + emit dataChanged(index(0,0,QModelIndex()),index(2,0,QModelIndex())); +} +RsIdentityListModel::EntryIndex::EntryIndex() + : type(ENTRY_TYPE_INVALID),category_index(0),identity_index(0) +{ +} + +// The index encodes the whole hierarchy of parents. This allows to very efficiently compute indices of the parent of an index. +// +// On 32 bits and 64 bits architectures the format is the following: +// +// 0x [2 bits] 00000 [24 bits] [2 bits] +// | | | +// | | +-------------- type (0=top level, 1=category, 2=identity) +// | +----------------------- identity index +// +-------------------------------------- category index +// + +bool RsIdentityListModel::convertIndexToInternalId(const EntryIndex& e,quintptr& id) +{ + // the internal id is set to the place in the table of items. We simply shift to allow 0 to mean something special. + + if(e.type == ENTRY_TYPE_INVALID) + { + RsErr() << "ERROR: asked for the internal id of an invalid EntryIndex" ; + id = 0; + return true; + } + if(bool(e.identity_index >> 24)) + { + RsErr() << "Cannot encode more than 2^24 identities. Somthing's wrong. e.identity_index = " << std::hex << e.identity_index << std::dec ; + id = 0; + return false; + } + + id = ((0x3 & (uint32_t)e.category_index) << 30) + ((uint32_t)e.identity_index << 2) + (0x3 & (uint32_t)e.type); + + return true; +} +bool RsIdentityListModel::convertInternalIdToIndex(quintptr ref,EntryIndex& e) +{ + // Compatible with ref=0 since it will cause type=TOP_LEVEL + + e.type = static_cast((ref >> 0) & 0x3) ;// 2 bits + e.identity_index = (ref >> 2) & 0xffffff;// 24 bits + e.category_index = (ref >> 30) & 0x3 ;// 2 bits + + return true; +} + +static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay) +{ + int avatarWidth = avatar.width(); + int avatarHeight = avatar.height(); + + QPixmap pixmap(avatar); + + int overlaySize = (avatarWidth > avatarHeight) ? (avatarWidth/2.5) : (avatarHeight/2.5); + int overlayX = avatarWidth - overlaySize; + int overlayY = avatarHeight - overlaySize; + + QPainter painter(&pixmap); + painter.drawPixmap(overlayX, overlayY, overlaySize, overlaySize, overlay); + + QIcon icon; + icon.addPixmap(pixmap); + return icon; +} + +void RsIdentityListModel::preMods() +{ + emit layoutAboutToBeChanged(); +} +void RsIdentityListModel::postMods() +{ + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(rowCount()-1,columnCount()-1,(void*)NULL)); + emit layoutChanged(); +} + +int RsIdentityListModel::rowCount(const QModelIndex& parent) const +{ + if(parent.column() >= COLUMN_THREAD_NB_COLUMNS) + return 0; + + EntryIndex index; + + if(!parent.isValid() || !convertInternalIdToIndex(parent.internalId(),index)) + return mCategories.size(); + + switch(index.type) + { + case ENTRY_TYPE_CATEGORY: return mCategories[index.category_index].child_identity_indices.size(); + case ENTRY_TYPE_TOP_LEVEL: return mCategories.size(); + default: + return 0; + } +} + +int RsIdentityListModel::columnCount(const QModelIndex &/*parent*/) const +{ + return COLUMN_THREAD_NB_COLUMNS ; +} + +bool RsIdentityListModel::hasChildren(const QModelIndex &parent) const +{ + if(!parent.isValid()) + return true; + + EntryIndex parent_index ; + convertInternalIdToIndex(parent.internalId(),parent_index); + + if(parent_index.type == ENTRY_TYPE_TOP_LEVEL) + return true; + + if(parent_index.type == ENTRY_TYPE_IDENTITY) + return false; + + if(parent_index.type == ENTRY_TYPE_CATEGORY) + return !mCategories[parent_index.category_index].child_identity_indices.empty(); + + return false; +} + +RsIdentityListModel::EntryIndex RsIdentityListModel::EntryIndex::parent() const +{ + EntryIndex i(*this); + + switch(type) + { + case ENTRY_TYPE_CATEGORY: i.type = ENTRY_TYPE_TOP_LEVEL; + i.category_index = 0; + i.identity_index = 0; + break; + + case ENTRY_TYPE_IDENTITY: i.type = ENTRY_TYPE_CATEGORY; + i.identity_index = 0; + break; + case ENTRY_TYPE_TOP_LEVEL: + std::cerr << "ERROR: calling parent() on entryindex with no parent!" << std::endl; + + default: + //Can be when request root index. + break; + } + + return i; +} + +RsIdentityListModel::EntryIndex RsIdentityListModel::EntryIndex::child(int row) const +{ + EntryIndex i; + + switch(type) + { + case ENTRY_TYPE_TOP_LEVEL: + i.type = ENTRY_TYPE_CATEGORY; + i.category_index = row; + i.identity_index = 0; + + break; + + case ENTRY_TYPE_CATEGORY: i.type = ENTRY_TYPE_IDENTITY; + i.category_index = category_index; + i.identity_index = row; + break; + + case ENTRY_TYPE_IDENTITY: i = EntryIndex(); + std::cerr << "ERROR: calling child() on entryindex with no children!" << std::endl; + default: + break; + } + + return i; + +} +uint32_t RsIdentityListModel::EntryIndex::parentRow() const +{ + switch(type) + { + default: + case ENTRY_TYPE_TOP_LEVEL: return -1; + case ENTRY_TYPE_CATEGORY : return -1; + case ENTRY_TYPE_IDENTITY : return category_index; + } +} + +QModelIndex RsIdentityListModel::index(int row, int column, const QModelIndex& parent) const +{ + if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) + return QModelIndex(); + + EntryIndex parent_index ; + convertInternalIdToIndex(parent.internalId(),parent_index); +#ifdef DEBUG_MODEL_INDEX + RsDbg() << "Index row=" << row << " col=" << column << " parent=" << parent << std::endl; +#endif + + quintptr ref; + EntryIndex new_index = parent_index.child(row); + convertIndexToInternalId(new_index,ref); + +#ifdef DEBUG_MODEL_INDEX + RsDbg() << " returning " << createIndex(row,column,ref) << std::endl; +#endif + + return createIndex(row,column,ref); +} + +QModelIndex RsIdentityListModel::parent(const QModelIndex& index) const +{ + if(!index.isValid()) + return QModelIndex(); + + EntryIndex I ; + convertInternalIdToIndex(index.internalId(),I); + + EntryIndex p = I.parent(); + + if(p.type == ENTRY_TYPE_TOP_LEVEL) + return QModelIndex(); + + quintptr i; + convertIndexToInternalId(p,i); + + return createIndex(I.parentRow(),0,i); +} + +Qt::ItemFlags RsIdentityListModel::flags(const QModelIndex& index) const +{ + if (!index.isValid()) + return Qt::ItemFlags(); + + return QAbstractItemModel::flags(index); +} + +QVariant RsIdentityListModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const +{ + if(role == Qt::DisplayRole) + switch(section) + { + case COLUMN_THREAD_NAME: return tr("Name"); + case COLUMN_THREAD_ID: return tr("Id"); + case COLUMN_THREAD_REPUTATION: return QVariant(); + case COLUMN_THREAD_OWNER_ID: return tr("Owner Id"); + case COLUMN_THREAD_OWNER_NAME: return tr("Owner"); + default: + return QVariant(); + } + if(role == Qt::DecorationRole && section == COLUMN_THREAD_REPUTATION) + return QIcon(":/icons/flag-green.png"); + + return QVariant(); +} + +QVariant RsIdentityListModel::data(const QModelIndex &index, int role) const +{ +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "calling data(" << index << ") role=" << role << std::endl; +#endif + + if(!index.isValid()) + return QVariant(); + + quintptr ref = (index.isValid())?index.internalId():0 ; + +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "data(" << index << ")" ; +#endif + + if(!ref) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << " [empty]" << std::endl; +#endif + return QVariant() ; + } + + EntryIndex entry; + + if(!convertInternalIdToIndex(ref,entry)) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "Bad pointer: " << (void*)ref << std::endl; +#endif + return QVariant() ; + } + + switch(role) + { + case Qt::SizeHintRole: return sizeHintRole(entry,index.column()) ; + case Qt::DisplayRole: return displayRole(entry,index.column()) ; + case Qt::FontRole: return fontRole(entry,index.column()) ; + case Qt::ForegroundRole: return foregroundRole(entry,index.column()) ; + case Qt::DecorationRole: return decorationRole(entry,index.column()) ; + + case FilterRole: return filterRole(entry,index.column()) ; + case SortRole: return sortRole(entry,index.column()) ; + case TreePathRole: return treePathRole(entry,index.column()) ; + + default: + return QVariant(); + } +} + +bool RsIdentityListModel::passesFilter(const EntryIndex& e,int /*column*/) const +{ + QString s ; + + if(mFilterStrings.empty() || e.type != ENTRY_TYPE_IDENTITY) + return true; + + auto passes_strings = [&](const QString& s) -> bool { + bool res = true; + + for(auto iter(mFilterStrings.begin()); iter != mFilterStrings.end(); ++iter) + res = res && s.contains(*iter,Qt::CaseInsensitive); + + return res; + }; + + if((mFilterType & FilterType::FILTER_TYPE_ID) && passes_strings(displayRole(e,COLUMN_THREAD_ID ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_NAME) && passes_strings(displayRole(e,COLUMN_THREAD_NAME ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_OWNER_ID) && passes_strings(displayRole(e,COLUMN_THREAD_OWNER_ID ).toString())) return true; + if((mFilterType & FilterType::FILTER_TYPE_OWNER_NAME) && passes_strings(displayRole(e,COLUMN_THREAD_OWNER_NAME).toString())) return true; + + return false; +} + +QVariant RsIdentityListModel::filterRole(const EntryIndex& e,int column) const +{ + if(passesFilter(e,column)) + return QVariant(FilterString); + + return QVariant(QString()); +} + +uint32_t RsIdentityListModel::updateFilterStatus(ForumModelIndex /*i*/,int /*column*/,const QStringList& /*strings*/) +{ + return 0; +} + + +void RsIdentityListModel::setFilter(uint8_t filter_type, const QStringList& strings) +{ +#ifdef DEBUG_MODEL + std::cerr << "Setting filter to filter_type=" << int(filter_type) << " and strings to " ; + foreach(const QString& str,strings) + std::cerr << "\"" << str.toStdString() << "\" " ; + std::cerr << std::endl; +#endif + + preMods(); + + mFilterType = filter_type; + mFilterStrings = strings; + + postMods(); +} + +QVariant RsIdentityListModel::toolTipRole(const EntryIndex& fmpe,int /*column*/) const +{ + switch(fmpe.type) + { + case ENTRY_TYPE_IDENTITY: + { + auto id_info = getIdentityInfo(fmpe); + + if(!id_info) + return QVariant(); + + if(id_info->flags & RS_IDENTITY_FLAGS_IS_DEPRECATED) + return QVariant( tr("\nThis identity has a insecure fingerprint (It's probably quite old).\nYou should get rid of it now and use a new one.\nThese identities are not supported anymore.") ) ; + + if(rsIdentity->isOwnId(id_info->id)) + return QVariant(tr("This identity is owned by you")); + + if(id_info->owner.isNull()) + return QVariant("Anonymous identity"); + else + { + RsPeerDetails dd; + if(rsPeers->getGPGDetails(id_info->owner,dd)) + return QVariant(tr("Identity owned by profile")+" \""+ QString::fromUtf8(dd.name.c_str()) +"\" ("+QString::fromStdString(id_info->owner.toStdString())); + else + return QVariant(tr("Identity possibly owned by unknown profile")+" \""+ QString::fromUtf8(dd.name.c_str()) +"\" ("+QString::fromStdString(id_info->owner.toStdString())); + } + } + + break; + case ENTRY_TYPE_CATEGORY: ; // fallthrough + default: + return QVariant(); + } +} + +QVariant RsIdentityListModel::sizeHintRole(const EntryIndex& e,int col) const +{ + float x_factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float y_factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + + if(e.type == ENTRY_TYPE_IDENTITY) + y_factor *= 1.0; + + if(e.type == ENTRY_TYPE_CATEGORY) + y_factor *= 1.5; + + std::cerr << "sizeHintRole()" << std::endl; + switch(col) + { + default: + case COLUMN_THREAD_REPUTATION: return QVariant( QSize(x_factor * 14 , y_factor*14*1.1f )); + + case COLUMN_THREAD_NAME: + case COLUMN_THREAD_ID: + case COLUMN_THREAD_OWNER_NAME: + case COLUMN_THREAD_OWNER_ID: return QFontMetricsF(QApplication::font()).boundingRect(displayRole(e,col).toString()).size(); + } +} + +QString RsIdentityListModel::indexIdentifier(QModelIndex index) +{ + quintptr ref = (index.isValid())?index.internalId():0 ; + +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << "data(" << index << ")" ; +#endif + + if(!ref) + { +#ifdef DEBUG_MESSAGE_MODEL + std::cerr << " [empty]" << std::endl; +#endif + return QString(); + } + + EntryIndex entry; + if(!convertInternalIdToIndex(ref,entry)) + return QString(); + + return treePathRole(entry,0).toString(); +} +QVariant RsIdentityListModel::treePathRole(const EntryIndex& entry,int /*column*/) const +{ + if(entry.type == ENTRY_TYPE_CATEGORY) + return QString::number((int)entry.category_index); + else + return QString::fromStdString(mIdentities[mCategories[entry.category_index].child_identity_indices[entry.identity_index]].id.toStdString()); +} +QVariant RsIdentityListModel::sortRole(const EntryIndex& entry,int column) const +{ + switch(column) + { + case COLUMN_THREAD_REPUTATION: return decorationRole(entry,column); + + case COLUMN_THREAD_ID: + case COLUMN_THREAD_OWNER_ID: + case COLUMN_THREAD_OWNER_NAME: + case COLUMN_THREAD_NAME: [[__fallthrough__]]; + default: + return displayRole(entry,column); + } +} + +QModelIndex RsIdentityListModel::getIndexOfIdentity(const RsGxsId& id) const +{ + for(uint i=0;iflags & RS_IDENTITY_FLAGS_IS_DEPRECATED) + return QVariant(QColor(Qt::red)); + + return QVariant(); +} +QVariant RsIdentityListModel::fontRole(const EntryIndex& e, int /*col*/) const +{ + QFont f; + f.setPointSize(mFontSize); + + auto it = getIdentityInfo(e); + + if(it) + { + RsGxsId id(it->id); + + if(rsIdentity->isOwnId(id)) + f.setBold(true); + } + + return QVariant(f); +} +void RsIdentityListModel::setFontSize(int s) +{ + if(s != mFontSize) + { + mFontSize = s; + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); + } +} + +#ifdef DEBUG_MODEL_INDEX + std::cerr << " font role " << e.type << ", (" << (int)e.group_index << ","<< (int)e.profile_index << ","<< (int)e.node_index << ") col="<< col<<": " << std::endl; +#endif + +#ifdef TODO + int status = onlineRole(e,col).toInt(); + + switch (status) + { + case RS_STATUS_INACTIVE: + { + QFont font ; + QTreeView* myParent = dynamic_cast(QAbstractItemModel::parent()); + if (myParent) + font = myParent->font(); + + font.setBold(true); + + return QVariant(font); + } + default: + return QVariant(); + } +#endif + +QVariant RsIdentityListModel::displayRole(const EntryIndex& e, int col) const +{ +#ifdef DEBUG_MODEL_INDEX + std::cerr << " Display role " << e.type << ", (" << (int)e.group_index << ","<< (int)e.profile_index << ","<< (int)e.node_index << ") col="<< col<<": "; +#endif + + switch(e.type) + { + case ENTRY_TYPE_CATEGORY: + { + const HierarchicalCategoryInformation *cat = getCategoryInfo(e); + + if(!cat) + return QVariant(); + + switch(col) + { + case COLUMN_THREAD_NAME: +#ifdef DEBUG_MODEL_INDEX + std::cerr << group->group_info.name.c_str() ; +#endif + + if(!cat->child_identity_indices.empty()) + return QVariant(cat->category_name+" (" + QString::number(cat->child_identity_indices.size()) + ")"); + else + return QVariant(cat->category_name); + + default: + return QVariant(); + } + } + break; + + case ENTRY_TYPE_IDENTITY: + { + const HierarchicalIdentityInformation *idinfo = getIdentityInfo(e); + const QString loading_string = "["+tr("Loading...")+"]"; + +#ifdef DEBUG_MODEL_INDEX + std::cerr << profile->profile_info.name.c_str() ; +#endif + if(col == COLUMN_THREAD_ID) return QVariant(QString::fromStdString(idinfo->id.toStdString()) ); + if(col == COLUMN_THREAD_REPUTATION) return QVariant(); + + if(idinfo->nickname.empty()) + return loading_string; + + switch(col) + { + case COLUMN_THREAD_NAME: return QVariant(QString::fromUtf8(idinfo->nickname.c_str())); + case COLUMN_THREAD_OWNER_NAME: if(idinfo->owner.isNull()) + return QVariant(); + else + return QVariant(QString::fromStdString(rsPeers->getGPGName(idinfo->owner)) ); + + case COLUMN_THREAD_OWNER_ID: if(idinfo->owner.isNull()) + return QVariant(); + else + return QVariant(QString::fromStdString(idinfo->owner.toStdString()) ); + default: + return QVariant(); + } + } + break; + + default: //ENTRY_TYPE + return QVariant(); + } +} + +// This function makes sure that the internal data gets updated. They are situations where the notification system cannot +// send the information about changes, such as when the computer is put on sleep. + +void RsIdentityListModel::checkInternalData(bool force) +{ + rstime_t now = time(NULL); + + if( (mLastInternalDataUpdate + MAX_INTERNAL_DATA_UPDATE_DELAY < now) || force) + updateIdentityList(); +} + +const RsIdentityListModel::HierarchicalCategoryInformation *RsIdentityListModel::getCategoryInfo(const EntryIndex& e) const +{ + if(e.category_index >= mCategories.size()) + return NULL ; + else + return &mCategories[e.category_index]; +} + +const RsIdentityListModel::HierarchicalIdentityInformation *RsIdentityListModel::getIdentityInfo(const EntryIndex& e) const +{ + // First look into the relevant group, then for the correct profile in this group. + + if(e.type != ENTRY_TYPE_IDENTITY) + return nullptr ; + + if(e.category_index >= mCategories.size()) + return nullptr ; + + if(e.identity_index < mCategories[e.category_index].child_identity_indices.size()) + { + auto& it(mIdentities[mCategories[e.category_index].child_identity_indices[e.identity_index]]); + rstime_t now = time(nullptr); + + if(now > it.last_update_TS + ID_DETAILS_UPDATE_DELAY) + { + RsIdentityDetails det; + if(rsIdentity->getIdDetails(it.id,det)) + { + it.nickname = det.mNickname; + it.owner = det.mPgpId; + it.flags = det.mFlags; + it.last_update_TS = now; + } + } + return ⁢ + } + else + { + RsErr() << "Inconsistent identity index!" ; + return nullptr; + } +} + +QVariant RsIdentityListModel::decorationRole(const EntryIndex& entry,int col) const +{ + switch(entry.type) + { + case ENTRY_TYPE_CATEGORY: + return QVariant(); + + case ENTRY_TYPE_IDENTITY: + { + const HierarchicalIdentityInformation *hn = getIdentityInfo(entry); + + if(!hn) + return QVariant(); + + if(col == COLUMN_THREAD_REPUTATION) + return QVariant( static_cast(rsReputations->overallReputationLevel(hn->id)) ); + else if(col == COLUMN_THREAD_NAME) + { + QPixmap sslAvatar; + RsIdentityDetails details ; + + if(!rsIdentity->getIdDetails(hn->id, details)) + { + mIdentityUpdateTimer->stop(); + mIdentityUpdateTimer->setSingleShot(true); + mIdentityUpdateTimer->start(500); + return QVariant(); + } + else if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, sslAvatar,GxsIdDetails::LARGE)) + return QVariant(QIcon(GxsIdDetails::makeDefaultIcon(hn->id,GxsIdDetails::SMALL))); + else + return QVariant(QIcon(sslAvatar)); + } + else + return QVariant(); + } + break; + + default: + return QVariant(); + } +} + +void RsIdentityListModel::clear() +{ + preMods(); + + mIdentities.clear(); + mCategories.clear(); + + mCategories.resize(3); + mCategories[0].category_name = tr("My own identities"); + mCategories[1].category_name = tr("My contacts"); + mCategories[2].category_name = tr("All"); + + postMods(); + + emit friendListChanged(); +} + + +void RsIdentityListModel::debug_dump() const +{ + std::cerr << "==== IdentityListModel Debug dump ====" << std::endl; + + std::cerr << "Invalid index : " << QModelIndex() << std::endl; + + EntryIndex top_level; + top_level.type = ENTRY_TYPE_TOP_LEVEL; + quintptr id; + convertIndexToInternalId(top_level,id); + + std::cerr << "Top level index: " << createIndex(0,0,id) << std::endl; + EntryIndex tei; + convertInternalIdToIndex(0,tei); + std::cerr << "Top level entry index: " << tei << std::endl; + + for(uint32_t j=0;jid; + else + return RsGxsId(); +} + +RsIdentityListModel::EntryType RsIdentityListModel::getType(const QModelIndex& i) const +{ + if(!i.isValid()) + return ENTRY_TYPE_TOP_LEVEL; + + EntryIndex e; + if(!convertInternalIdToIndex(i.internalId(),e)) + return ENTRY_TYPE_TOP_LEVEL; + + return e.type; +} + +int RsIdentityListModel::getCategory(const QModelIndex& i) const +{ + if(!i.isValid()) + return CATEGORY_ALL; + + EntryIndex e; + if(!convertInternalIdToIndex(i.internalId(),e)) + return CATEGORY_ALL; + + return e.category_index; +} +void RsIdentityListModel::setIdentities(const std::list& identities_meta) +{ + preMods(); + beginResetModel(); + clear(); + + for(auto id:identities_meta) + { + HierarchicalIdentityInformation idinfo; + idinfo.id = RsGxsId(id.mGroupId); + idinfo.last_update_TS = 0;// forces update + + if(rsIdentity->isOwnId(idinfo.id)) + mCategories[CATEGORY_OWN].child_identity_indices.push_back(mIdentities.size()); + else if(rsIdentity->isARegularContact(RsGxsId(id.mGroupId))) + mCategories[CATEGORY_CTS].child_identity_indices.push_back(mIdentities.size()); + else + mCategories[CATEGORY_ALL].child_identity_indices.push_back(mIdentities.size()); + + mIdentities.push_back(idinfo); + } + + if (mCategories.size()>0) + { + beginInsertRows(QModelIndex(),0,mCategories.size()-1); + endInsertRows(); + } + + endResetModel(); + postMods(); + + mLastInternalDataUpdate = time(NULL); + +} + +void RsIdentityListModel::updateIdentityList() +{ + std::cerr << "Updating identity list" << std::endl; + + std::list ids ; + + if(!rsIdentity->getIdentitiesSummaries(ids)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve identity metadata." << std::endl; + return; + } + + setIdentities(ids) ; + + debug_dump(); +} + + + +void RsIdentityListModel::collapseItem(const QModelIndex& index) +{ + if(getType(index) != ENTRY_TYPE_CATEGORY) + return; + + EntryIndex entry; + + if(!convertInternalIdToIndex(index.internalId(),entry)) + return; + + mExpandedCategories[entry.category_index] = false; + + // apparently we cannot be subtle here. + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); +} + +void RsIdentityListModel::expandItem(const QModelIndex& index) +{ + if(getType(index) != ENTRY_TYPE_CATEGORY) + return; + + EntryIndex entry; + + if(!convertInternalIdToIndex(index.internalId(),entry)) + return; + + mExpandedCategories[entry.category_index] = true; + + // apparently we cannot be subtle here. + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mCategories.size()-1,columnCount()-1,(void*)NULL)); +} + + + diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.h b/retroshare-gui/src/gui/Identity/IdentityListModel.h new file mode 100644 index 000000000..4c3cb43e2 --- /dev/null +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.h @@ -0,0 +1,252 @@ +/******************************************************************************* + * retroshare-gui/src/gui/msgs/RsFriendListModel.h * + * * + * Copyright 2019 by Cyril Soler * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#pragma once + +#include +#include + +#include "retroshare/rsstatus.h" +#include "retroshare/rsmsgs.h" +#include "retroshare/rspeers.h" +#include "retroshare/rsidentity.h" + +typedef uint32_t ForumModelIndex; + +// This class is the item model used by Qt to display the information + +class QTimer; + +class RsIdentityListModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit RsIdentityListModel(QObject *parent = NULL); + ~RsIdentityListModel(){} + + enum Columns { + COLUMN_THREAD_NAME = 0x00, + COLUMN_THREAD_ID = 0x01, + COLUMN_THREAD_OWNER_NAME = 0x02, + COLUMN_THREAD_OWNER_ID = 0x03, + COLUMN_THREAD_REPUTATION = 0x04, + COLUMN_THREAD_NB_COLUMNS = 0x05 + }; + + enum Roles{ SortRole = Qt::UserRole+1, + StatusRole = Qt::UserRole+2, + UnreadRole = Qt::UserRole+3, + FilterRole = Qt::UserRole+4, + TreePathRole = Qt::UserRole+5, + }; + + enum FilterType{ FILTER_TYPE_NONE = 0x00, + FILTER_TYPE_ID = 0x01, + FILTER_TYPE_NAME = 0x02, + FILTER_TYPE_OWNER_NAME = 0x04, + FILTER_TYPE_OWNER_ID = 0x08 + }; + + enum EntryType{ ENTRY_TYPE_TOP_LEVEL = 0x00, + ENTRY_TYPE_CATEGORY = 0x01, + ENTRY_TYPE_IDENTITY = 0x02, + ENTRY_TYPE_INVALID = 0x03 + }; + + enum Category{ CATEGORY_OWN = 0x00, + CATEGORY_CTS = 0x01, + CATEGORY_ALL = 0x02 + }; + + struct HierarchicalCategoryInformation + { + QString category_name; + std::vector child_identity_indices; // index in the array of hierarchical profiles + }; + + // This stores all the info that is useful avoiding a call to the more expensive getIdDetails() + // + struct HierarchicalIdentityInformation + { + rstime_t last_update_TS; + RsGxsId id; + RsPgpId owner; + uint32_t flags; + std::string nickname; + }; + + // This structure encodes the position of a node in the hierarchy. The type tells which of the index fields are valid. + + struct EntryIndex + { + public: + EntryIndex(); + + EntryType type; // type of the entry (group,profile,location) + + friend std::ostream& operator<<(std::ostream& o, const EntryIndex& e) + { + o << "[" ; + switch(e.type) + { + case RsIdentityListModel::ENTRY_TYPE_INVALID: o << "Invalid," ; break; + case RsIdentityListModel::ENTRY_TYPE_CATEGORY: o << "Category," ; break; + case RsIdentityListModel::ENTRY_TYPE_IDENTITY: o << "Identity," ; break; + case RsIdentityListModel::ENTRY_TYPE_TOP_LEVEL: o << "Toplevel," ; break; + } + o << " CI: " << e.category_index << ", "; + o << " II: " << e.identity_index << "]"; + return o; + } + + // Indices w.r.t. parent. The set of indices entirely determines the position of the entry in the hierarchy. + // An index of 0xff means "undefined" + + uint16_t category_index; // index of the category in the mCategory array + uint16_t identity_index; // index of the identity in its own category + + EntryIndex parent() const; + EntryIndex child(int row) const; + uint32_t parentRow() const; + }; + + QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} + QModelIndex getIndexOfIdentity(const RsGxsId& id) const; + QModelIndex getIndexOfCategory(Category id) const; + + void updateIdentityList(); + + int count() const { return mIdentities.size() ; } // total number of identities + + static const QString FilterString ; + + // This method will asynchroneously update the data + + EntryType getType(const QModelIndex&) const; + RsGxsId getIdentity(const QModelIndex&) const; + int getCategory(const QModelIndex&) const; + void setFontSize(int s); + + void setFilter(uint8_t filter_type, const QStringList& strings) ; + + void expandItem(const QModelIndex&) ; + void collapseItem(const QModelIndex&) ; + + // Overloaded methods from QAbstractItemModel + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; + + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + void clear() ; + QString indexIdentifier(QModelIndex i); + + /* Color definitions (for standard see default.qss) */ + QColor mTextColorGroup; + QColor mTextColorStatus[RS_STATUS_COUNT]; + + void setIdentities(const std::list& identities_meta); + +private: + const HierarchicalCategoryInformation *getCategoryInfo (const EntryIndex&) const; + const HierarchicalIdentityInformation *getIdentityInfo(const EntryIndex&) const; + + void checkIdentity(HierarchicalIdentityInformation& node); + + QVariant sizeHintRole (const EntryIndex& e, int col) const; + QVariant displayRole (const EntryIndex& e, int col) const; + QVariant decorationRole(const EntryIndex& e, int col) const; + QVariant toolTipRole (const EntryIndex& e, int col) const; + QVariant statusRole (const EntryIndex& e, int col) const; + QVariant sortRole (const EntryIndex& e, int col) const; + QVariant fontRole (const EntryIndex& e, int col) const; + QVariant foregroundRole(const EntryIndex& e, int col) const; + QVariant textColorRole (const EntryIndex& e, int col) const; + QVariant filterRole (const EntryIndex& e, int col) const; + QVariant treePathRole (const EntryIndex& entry,int column) const; + + /*! + * \brief debug_dump + * Dumps the hierarchy of posts in the terminal, to allow checking whether the internal representation is correct. + */ + +public slots: + void checkInternalData(bool force); + void debug_dump() const; + void timerUpdate(); + +signals: + void dataLoaded(); // emitted after the messages have been set. Can be used to updated the UI. + void friendListChanged(); // emitted after the messages have been set. Can be used to updated the UI. + void dataAboutToLoad(); + +private: + bool passesFilter(const EntryIndex &e, int column) const; + + void preMods() ; + void postMods() ; + + void *getParentRef(void *ref,int& row) const; + void *getChildRef(void *ref,int row) const; + int getChildrenCount(void *ref) const; + + static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref); + static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e); + + uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings); + + QStringList mFilterStrings; + uint8_t mFilterType; + int mFontSize; + + rstime_t mLastInternalDataUpdate; + rstime_t mLastNodeUpdate;; + + // The 3 vectors below store thehierarchical information for groups, profiles and locations, + // meaning which is the child/parent of which. The actual group/profile/node data are also stored in the + // structure. + + mutable std::vector mCategories; + mutable std::vector mIdentities; + + // The top level list contains all nodes to display, which type depends on the option to display groups or not. + // Idices in the list may be profile indices or group indices. In the former case the profile child index refers to + // the inde in the mProfiles tab, whereas in the the later case, the child index refers to the index of the profile in the + // group it belows to. + + std::vector mTopLevel; + + // keeps track of expanded/collapsed items, so as to only show icon for collapsed profiles + + std::vector mExpandedCategories; + + // List of identities for which getIdDetails() failed, to be requested again. + mutable QTimer *mIdentityUpdateTimer; +}; + + diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index b1e4b1e69..da25bc2c6 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -360,6 +360,8 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); settingsChanged(); + + mFontSizeHandler.registerFontSize(ui->listWidget, 1.5f); } /** Destructor. */ @@ -564,6 +566,11 @@ void MainWindow::addPage(MainPage *page, QActionGroup *grp, QListiconPixmap()),page->pageName()) ; ui->listWidget->addItem(item) ; +#if defined(Q_OS_DARWIN) + QFont f = ui->toolBarPage->font(); + action->setFont(f); +#endif + if (notify) { QPair pair = QPair( action, item); @@ -1022,6 +1029,7 @@ void SetForegroundWindowInternal(HWND hWnd) /* Show the dialog. */ raiseWindow(); + /* Set the focus to the specified page. */ _instance->ui->stackPages->setCurrentPage(page); } diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index a7f3013f1..b435524f0 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -27,6 +27,7 @@ #include "gui/common/rwindow.h" #include "gui/common/RSComboBox.h" +#include "util/FontSizeHandler.h" namespace Ui { class MainWindow; @@ -371,6 +372,8 @@ private: void setIdle(bool Idle); bool isIdle; + FontSizeHandler mFontSizeHandler; + Ui::MainWindow *ui ; }; diff --git a/retroshare-gui/src/gui/MainWindow.ui b/retroshare-gui/src/gui/MainWindow.ui index 55a7145e0..796593dfd 100644 --- a/retroshare-gui/src/gui/MainWindow.ui +++ b/retroshare-gui/src/gui/MainWindow.ui @@ -33,11 +33,6 @@ 0 - - - 12 - - QFrame::NoFrame @@ -157,7 +152,7 @@ - + :/images/kcmsystem24.png:/images/kcmsystem24.png diff --git a/retroshare-gui/src/gui/NewsFeed.ui b/retroshare-gui/src/gui/NewsFeed.ui index 32a679a74..ff8c17f5e 100644 --- a/retroshare-gui/src/gui/NewsFeed.ui +++ b/retroshare-gui/src/gui/NewsFeed.ui @@ -70,8 +70,8 @@ - 12 - 75 + 12 + 75 true diff --git a/retroshare-gui/src/gui/Posted/PhotoView.ui b/retroshare-gui/src/gui/Posted/PhotoView.ui index e1e7a21e5..31db767c9 100644 --- a/retroshare-gui/src/gui/Posted/PhotoView.ui +++ b/retroshare-gui/src/gui/Posted/PhotoView.ui @@ -22,7 +22,6 @@ MS Sans Serif - 11 75 true true @@ -103,7 +102,6 @@ MS Sans Serif - 9 50 false @@ -114,7 +112,7 @@
- + 24 @@ -134,7 +132,6 @@ MS Sans Serif - 11 75 true true @@ -150,7 +147,6 @@ MS Sans Serif - 9 @@ -163,7 +159,6 @@ MS Sans Serif - 9 @@ -209,17 +204,17 @@ + + AvatarWidget + QLabel +
gui/common/AvatarWidget.h
+ 1 +
GxsIdLabel QLabel
gui/gxs/GxsIdLabel.h
- - AvatarWidget - QWidget -
gui/common/AvatarWidget.h
- 1 -
AspectRatioPixmapLabel QLabel diff --git a/retroshare-gui/src/gui/Posted/PostedItem.ui b/retroshare-gui/src/gui/Posted/PostedItem.ui index 24d570b16..ad37a936c 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.ui +++ b/retroshare-gui/src/gui/Posted/PostedItem.ui @@ -44,10 +44,10 @@ false - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -262,7 +262,6 @@ - 11 75 true true diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui index 8074388dc..734c4a233 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui @@ -54,7 +54,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html> @@ -355,10 +355,10 @@ p, li { white-space: pre-wrap; } - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -576,37 +576,10 @@ p, li { white-space: pre-wrap; } - - ElidedLabel - QLabel -
gui/common/ElidedLabel.h
- 1 -
- - GxsIdChooser - QComboBox -
gui/gxs/GxsIdChooser.h
-
- - GxsIdLabel - QLabel -
gui/gxs/GxsIdLabel.h
-
LineEditClear QLineEdit -
gui/common/LineEditClear.h
-
- - RSComboBox - QComboBox -
gui/common/RSComboBox.h
-
- - RSTabWidget - QTabWidget -
gui/common/RSTabWidget.h
- 1 +
gui/common/LineEditClear.h
RSTreeView @@ -614,15 +587,42 @@ p, li { white-space: pre-wrap; }
gui/common/RSTreeView.h
1
+ + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
+ + ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
SubscribeToolButton QToolButton
gui/common/SubscribeToolButton.h
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
+ + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
+
+ + RSTabWidget + QTabWidget +
gui/common/RSTabWidget.h
+ 1 +
- + diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h index 18943c1dc..1b3995cd7 100644 --- a/retroshare-gui/src/gui/RSHumanReadableDelegate.h +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -88,11 +88,16 @@ class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate public: virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const { + painter->save(); QStyleOptionViewItem opt(option) ; setPainterOptions(painter,opt,index) ; - if(index.data().toLongLong() > 0) // no date is present. - painter->drawText(opt.rect, Qt::AlignCenter, misc::timeRelativeToNow(index.data().toLongLong())) ; + if(index.data().toLongLong() > 0) { // no date is present. + painter->setFont(opt.font); + painter->drawText(opt.rect, opt.displayAlignment, misc::timeRelativeToNow(index.data().toLongLong())) ; + } + + painter->restore(); } }; @@ -101,10 +106,14 @@ class RSHumanReadableSizeDelegate: public RSHumanReadableDelegate public: virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const { + painter->save(); QStyleOptionViewItem opt(option) ; setPainterOptions(painter,opt,index) ; - painter->drawText(opt.rect, Qt::AlignRight, misc::friendlyUnit(index.data().toULongLong())); + painter->setFont(opt.font); + painter->drawText(opt.rect, opt.displayAlignment, misc::friendlyUnit(index.data().toULongLong())); + + painter->restore(); } }; diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index fd3571e7e..0001cd9bc 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -1920,7 +1920,9 @@ static void processList(const QStringList &list, const QString &textSingular, co void RSLinkClipboard::copyLinks(const QList& links) { QString res ; - for (int i = 0; i < links.size(); ++i) + if(links.size() == 1) + res += links[0].toString(); + else for(int i = 0; i < links.size(); ++i) res += links[i].toString() + "\n" ; QApplication::clipboard()->setText(res) ; @@ -2036,4 +2038,3 @@ void RSLinkClipboard::parseText(QString text, QList &links,Retro pos += rx.matchedLength(); } } - diff --git a/retroshare-gui/src/gui/StartDialog.cpp b/retroshare-gui/src/gui/StartDialog.cpp index bc98527da..237d1bb83 100644 --- a/retroshare-gui/src/gui/StartDialog.cpp +++ b/retroshare-gui/src/gui/StartDialog.cpp @@ -161,7 +161,7 @@ void StartDialog::notSecureWarning() QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your Keychain. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); #else // this handles all linux systems at once. - QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your Gnome Keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); + QMessageBox::warning ( this, tr("Warning"), tr("The password to your SSL certificate (your node) will be stored encrypted in your desktop's keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); #endif #endif } diff --git a/retroshare-gui/src/gui/StartDialog.ui b/retroshare-gui/src/gui/StartDialog.ui index 8c491caeb..39287a797 100644 --- a/retroshare-gui/src/gui/StartDialog.ui +++ b/retroshare-gui/src/gui/StartDialog.ui @@ -345,8 +345,8 @@ The current identities/locations will not be affected. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">New Profile/Node</span></a></p></body></html> +</style></head><body style=" font-family:'Sans'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; text-decoration: underline; color:#366fe0;">New Profile/Node</span></a></p></body></html>
@@ -370,8 +370,8 @@ p, li { white-space: pre-wrap; } - + diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index 3b92883e8..dd4a128a4 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -208,6 +208,8 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi connect(unsubscribeButton, SIGNAL(clicked()), this , SLOT(leaveLobby())); getChatWidget()->addTitleBarWidget(unsubscribeButton) ; + + mFontSizeHandler.registerFontSize(ui.participantsList); } void ChatLobbyDialog::leaveLobby() diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index 065abacee..c3572cc4b 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -26,6 +26,7 @@ #include "gui/common/RSTreeWidgetItem.h" #include "ChatDialog.h" #include "PopupChatWindow.h" +#include "util/FontSizeHandler.h" // Q_DECLARE_METATYPE(RsGxsId) // Q_DECLARE_METATYPE(QList) @@ -115,6 +116,8 @@ private: bool mWindowedSetted; PopupChatWindow* mPCWindow; + FontSizeHandler mFontSizeHandler; + /** Qt Designer generated object */ Ui::ChatLobbyDialog ui; diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui index 0851eba15..e00790f83 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui @@ -80,10 +80,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/common/FriendListModel.cpp b/retroshare-gui/src/gui/common/FriendListModel.cpp index 35cefa7ac..45c054698 100644 --- a/retroshare-gui/src/gui/common/FriendListModel.cpp +++ b/retroshare-gui/src/gui/common/FriendListModel.cpp @@ -162,12 +162,14 @@ static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay) void RsFriendListModel::setDisplayStatusString(bool b) { + preMods(); mDisplayStatusString = b; postMods(); } void RsFriendListModel::setDisplayStatusIcon(bool b) { + preMods(); mDisplayStatusIcon = b; postMods(); } @@ -302,10 +304,10 @@ uint32_t RsFriendListModel::EntryIndex::parentRow(uint32_t nb_groups) const switch(type) { default: - case ENTRY_TYPE_UNKNOWN : return 0; - case ENTRY_TYPE_GROUP : return group_index; - case ENTRY_TYPE_PROFILE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(profile_index+nb_groups):profile_index; - case ENTRY_TYPE_NODE : return node_index; + case ENTRY_TYPE_UNKNOWN : return -1; + case ENTRY_TYPE_GROUP : return -1; + case ENTRY_TYPE_PROFILE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(-1):group_index; + case ENTRY_TYPE_NODE : return (group_index==UNDEFINED_GROUP_INDEX_VALUE)?(profile_index+nb_groups):profile_index; } } diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp index 4608d1796..d9fc4b8dc 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.cpp @@ -135,6 +135,8 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent) mEventHandlerId_peers = 0; rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }) ;}, mEventHandlerId_peers, RsEventType::PEER_CONNECTION ); + + mFontSizeHandler.registerFontSize(ui->friendList); } void FriendSelectionWidget::handleEvent_main_thread(std::shared_ptr event) diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.h b/retroshare-gui/src/gui/common/FriendSelectionWidget.h index f10a748fc..425e16774 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.h +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.h @@ -26,6 +26,7 @@ #include "retroshare/rsevents.h" #include +#include "util/FontSizeHandler.h" namespace Ui { class FriendSelectionWidget; @@ -178,6 +179,8 @@ private: std::set mPreSelectedIds; // because loading of GxsIds is asynchroneous we keep selected Ids from the client in a list here and use it to initialize after loading them. + FontSizeHandler mFontSizeHandler; + RsEventsHandlerId_t mEventHandlerId_identities; RsEventsHandlerId_t mEventHandlerId_peers; }; diff --git a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui index 065c9013b..a9bc8b407 100644 --- a/retroshare-gui/src/gui/common/FriendSelectionWidget.ui +++ b/retroshare-gui/src/gui/common/FriendSelectionWidget.ui @@ -38,11 +38,6 @@ 0 - - - 11 - - Qt::CustomContextMenu @@ -71,7 +66,7 @@ LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
RSTreeWidget diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp index 0597a652c..43861c4c6 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -148,7 +148,19 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) : connect(ui->distantSearchLineEdit,SIGNAL(returnPressed()),this,SLOT(distantSearch())) ; - ui->treeWidget->setIconSize(QSize(H*1.8,H*1.8)); + mFontSizeHandler.registerFontSize(ui->treeWidget, 1.8f, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QTreeWidgetItemIterator it(ui->treeWidget); + while (*it) { + QTreeWidgetItem *item = *it; + + QFont font = item->font(GTW_COLUMN_NAME); + font.setPointSize(fontSize); + item->setFont(GTW_COLUMN_NAME, font); + + ++it; + } + }); } GroupTreeWidget::~GroupTreeWidget() @@ -254,8 +266,8 @@ QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIc RSTreeWidgetItem *item = new RSTreeWidgetItem(); ui->treeWidget->addTopLevelItem(item); // To get StyleSheet for Items - ui->treeWidget->style()->unpolish(ui->treeWidget); - ui->treeWidget->style()->polish(ui->treeWidget); +// ui->treeWidget->style()->unpolish(ui->treeWidget); +// ui->treeWidget->style()->polish(ui->treeWidget); item->setText(GTW_COLUMN_NAME, name); item->setData(GTW_COLUMN_DATA, ROLE_NAME, name); @@ -390,7 +402,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList< if (item == NULL) { item = new RSTreeWidgetItem(compareRole); item->setData(GTW_COLUMN_DATA, ROLE_ID, itemInfo.id); - item->setFont(GTW_COLUMN_DATA, ui->treeWidget->font()); + item->setFont(GTW_COLUMN_NAME, ui->treeWidget->font()); //static_cast(item)->setNoDataAsLast(true); //Uncomment this to sort data with QVariant() always at end. categoryItem->addChild(item); } diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.h b/retroshare-gui/src/gui/common/GroupTreeWidget.h index b27c37014..4aadb1c51 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.h +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.h @@ -25,6 +25,7 @@ #include #include +#include "util/FontSizeHandler.h" class QToolButton; class RshareSettings; @@ -163,6 +164,7 @@ private: // Compare role used for each column RSTreeWidgetItemCompareRole *compareRole; + FontSizeHandler mFontSizeHandler; Ui::GroupTreeWidget *ui; }; diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.ui b/retroshare-gui/src/gui/common/GroupTreeWidget.ui index d3e0a14a5..10b5eb48b 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.ui +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.ui @@ -35,10 +35,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -70,11 +70,6 @@ 0 - - - 11 - - Qt::CustomContextMenu diff --git a/retroshare-gui/src/gui/common/NewFriendList.cpp b/retroshare-gui/src/gui/common/NewFriendList.cpp index 6acb8da9a..38e141e86 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.cpp +++ b/retroshare-gui/src/gui/common/NewFriendList.cpp @@ -273,6 +273,8 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)),Qt::QueuedConnection); connect(h, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint))); + mFontSizeHandler.registerFontSize(ui->peerTreeWidget,1.5f); + // #ifdef RS_DIRECT_CHAT // connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatNode())); // #endif diff --git a/retroshare-gui/src/gui/common/NewFriendList.h b/retroshare-gui/src/gui/common/NewFriendList.h index 7424bcfcf..cf4c68e6f 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.h +++ b/retroshare-gui/src/gui/common/NewFriendList.h @@ -29,6 +29,7 @@ #include "FriendListModel.h" #include "retroshare/rsstatus.h" +#include "util/FontSizeHandler.h" namespace Ui { class NewFriendList; @@ -104,6 +105,7 @@ private: Ui::NewFriendList *ui; RsFriendListModel *mModel; QAction *mActionSortByState; + FontSizeHandler mFontSizeHandler; void applyWhileKeepingTree(std::function predicate); diff --git a/retroshare-gui/src/gui/common/NewFriendList.ui b/retroshare-gui/src/gui/common/NewFriendList.ui index f41d88a8b..286cf4304 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.ui +++ b/retroshare-gui/src/gui/common/NewFriendList.ui @@ -29,10 +29,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -58,11 +58,6 @@ - - - 12 - - Qt::CustomContextMenu diff --git a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui index cd0265c1d..db4ac6b1a 100644 --- a/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui +++ b/retroshare-gui/src/gui/feeds/ChannelsCommentsItem.ui @@ -6,8 +6,8 @@ 0 0 - 755 - 157 + 836 + 160 @@ -35,10 +35,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui index e17f53c48..43537d061 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsChannelGroupItem.ui @@ -7,7 +7,7 @@ 0 0 618 - 176 + 189 @@ -134,10 +134,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui index 578fa1637..d4d41dc06 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.ui @@ -7,7 +7,7 @@ 0 0 1092 - 231 + 255 @@ -41,10 +41,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.ui b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui index 7a77f5bda..374e8f84d 100644 --- a/retroshare-gui/src/gui/feeds/GxsCircleItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.ui @@ -7,7 +7,7 @@ 0 0 618 - 108 + 128 @@ -126,10 +126,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -317,7 +317,7 @@ Revoke - + :/images/cancel.png:/images/cancel.png diff --git a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui index 152d4951d..aee325282 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsForumGroupItem.ui @@ -126,10 +126,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui index 89aec4e1b..4a080effb 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui @@ -99,10 +99,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/MsgItem.ui b/retroshare-gui/src/gui/feeds/MsgItem.ui index b195e80c6..cf0a3ac08 100644 --- a/retroshare-gui/src/gui/feeds/MsgItem.ui +++ b/retroshare-gui/src/gui/feeds/MsgItem.ui @@ -6,8 +6,8 @@ 0 0 - 707 - 180 + 777 + 234 @@ -35,10 +35,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/PeerItem.ui b/retroshare-gui/src/gui/feeds/PeerItem.ui index 603002f7f..2433cdf09 100644 --- a/retroshare-gui/src/gui/feeds/PeerItem.ui +++ b/retroshare-gui/src/gui/feeds/PeerItem.ui @@ -7,7 +7,7 @@ 0 0 476 - 283 + 328 @@ -38,10 +38,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/PostedGroupItem.ui b/retroshare-gui/src/gui/feeds/PostedGroupItem.ui index b525facb9..6c043972f 100644 --- a/retroshare-gui/src/gui/feeds/PostedGroupItem.ui +++ b/retroshare-gui/src/gui/feeds/PostedGroupItem.ui @@ -7,7 +7,7 @@ 0 0 618 - 161 + 195 @@ -126,10 +126,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/SecurityIpItem.ui b/retroshare-gui/src/gui/feeds/SecurityIpItem.ui index 11a742880..53f4172b9 100644 --- a/retroshare-gui/src/gui/feeds/SecurityIpItem.ui +++ b/retroshare-gui/src/gui/feeds/SecurityIpItem.ui @@ -7,7 +7,7 @@ 0 0 763 - 185 + 205 @@ -38,10 +38,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/SecurityItem.ui b/retroshare-gui/src/gui/feeds/SecurityItem.ui index bc0524d18..585c18e00 100644 --- a/retroshare-gui/src/gui/feeds/SecurityItem.ui +++ b/retroshare-gui/src/gui/feeds/SecurityItem.ui @@ -7,7 +7,7 @@ 0 0 1015 - 246 + 326 @@ -35,10 +35,10 @@ true - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.ui b/retroshare-gui/src/gui/feeds/SubFileItem.ui index 8fdd8230d..d869fc7b8 100644 --- a/retroshare-gui/src/gui/feeds/SubFileItem.ui +++ b/retroshare-gui/src/gui/feeds/SubFileItem.ui @@ -29,10 +29,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index b1961a6e6..5c1c11b49 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -85,23 +85,27 @@ void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem { Q_ASSERT(index.isValid()); - QStyleOptionViewItemV4 opt = option; + QStyleOptionViewItem opt(option); initStyleOption(&opt, index); // disable default icon opt.icon = QIcon(); // draw default item QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0); - const QRect r = option.rect; + const QRect r = option.rect; // get pixmap - unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole)); + auto v = index.data(Qt::DecorationRole); + + if(!v.canConvert(QVariant::Int)) + return; + + unsigned int icon_index = qvariant_cast(v); if(icon_index > mMaxLevelToDisplay) return ; - QIcon icon = GxsIdDetails::getReputationIcon( - RsReputationLevel(icon_index), 0xff ); + QIcon icon = GxsIdDetails::getReputationIcon( RsReputationLevel(icon_index), 0xff ); QPixmap pix = icon.pixmap(r.size()); @@ -110,6 +114,12 @@ void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem painter->drawPixmap(r.topLeft() + p, pix); } +QSize ReputationItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const +{ + int s = 1.5*QFontMetricsF(option.font).height(); + + return QSize(s,s); +} /* The global object */ GxsIdDetails *GxsIdDetails::mInstance = NULL ; diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h index 05568aa3a..122b5e089 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h @@ -52,7 +52,8 @@ public: ReputationItemDelegate(RsReputationLevel max_level_to_display) : mMaxLevelToDisplay(static_cast(max_level_to_display)) {} - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const override; private: uint32_t mMaxLevelToDisplay ; diff --git a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui index 510da23a1..01e58118f 100644 --- a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui +++ b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.ui @@ -191,8 +191,8 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">Attachments:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Use Drag and Drop / Add Files button, to Hash new files.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Copy/Paste RetroShare links from your shares</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:''; font-size:;"> Use Drag and Drop / Add Files button, to Hash new files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-family:''; font-size:;"> Copy/Paste RetroShare links from your shares</span></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -515,8 +515,8 @@ p, li { white-space: pre-wrap; } 0 0 - 63 - 24 + 98 + 30 @@ -611,6 +611,11 @@ p, li { white-space: pre-wrap; }
+ + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
ChannelPostThumbnailView QWidget @@ -629,15 +634,10 @@ p, li { white-space: pre-wrap; }
util/RichTextEdit.h
1
- - RSComboBox - QComboBox -
gui/common/RSComboBox.h
-
- + diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui index 6bd0fb86b..2740b4654 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.ui @@ -29,10 +29,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -402,7 +402,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html> diff --git a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui index 10105a630..bae7223e3 100644 --- a/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui +++ b/retroshare-gui/src/gui/gxsforums/CreateGxsForumMsg.ui @@ -7,7 +7,7 @@ 0 0 640 - 465 + 551 @@ -34,7 +34,14 @@ 0 - + + + QFrame::StyledPanel + + + QFrame::Raised + + @@ -132,17 +139,12 @@ - - - MS Sans Serif - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> +</style></head><body style=" font-family:''; font-size:; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> @@ -155,10 +157,10 @@ p, li { white-space: pre-wrap; } - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -382,6 +384,11 @@ p, li { white-space: pre-wrap; } + + MimeTextEdit + QTextEdit +
gui/common/MimeTextEdit.h
+
GxsIdChooser QComboBox @@ -399,15 +406,10 @@ p, li { white-space: pre-wrap; }
gui/common/HashBox.h
1
- - MimeTextEdit - QTextEdit -
gui/common/MimeTextEdit.h
-
- + diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp index b68a50173..18f518749 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumModel.cpp @@ -46,6 +46,7 @@ RsGxsForumModel::RsGxsForumModel(QObject *parent) : QAbstractItemModel(parent), mUseChildTS(false),mFilteringEnabled(false),mTreeMode(TREE_MODE_TREE) { initEmptyHierarchy(mPosts); + mFont = QApplication::font(); } void RsGxsForumModel::preMods() @@ -399,7 +400,7 @@ QVariant RsGxsForumModel::data(const QModelIndex &index, int role) const if(role == Qt::FontRole) { - QFont font ; + QFont font = mFont; font.setBold( (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_HAS_UNREAD_CHILDREN) || IS_MSG_UNREAD(fmpe.mMsgStatus)); return QVariant(font); } @@ -533,6 +534,15 @@ void RsGxsForumModel::setFilter(int column,const QStringList& strings,uint32_t& postMods(); } +void RsGxsForumModel::setFont(const QFont &font) +{ + preMods(); + + mFont = font; + + postMods(); +} + QVariant RsGxsForumModel::missingRole(const ForumModelPostEntry& fmpe,int /*column*/) const { if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING) @@ -562,7 +572,7 @@ QVariant RsGxsForumModel::toolTipRole(const ForumModelPostEntry& fmpe,int column if(!GxsIdDetails::MakeIdDesc(fmpe.mAuthorId, true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) return QVariant(); - int S = QFontMetricsF(QApplication::font()).height(); + int S = QFontMetricsF(mFont).height(); QImage pix( (*icons.begin()).pixmap(QSize(5*S,5*S)).toImage()); QString embeddedImage; @@ -599,7 +609,7 @@ QVariant RsGxsForumModel::backgroundRole(const ForumModelPostEntry& fmpe,int /*c QVariant RsGxsForumModel::sizeHintRole(int col) const { - float factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float factor = QFontMetricsF(mFont).height()/14.0f ; switch(col) { @@ -650,7 +660,7 @@ QVariant RsGxsForumModel::displayRole(const ForumModelPostEntry& fmpe,int col) c case COLUMN_THREAD_TITLE: if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_REDACTED) return QVariant(tr("[ ... Redacted message ... ]")); // else if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED) -// return QVariant( QString("").arg(QFontMetricsF(QFont()).height()) +// return QVariant( QString("").arg(QFontMetricsF(mFont).height()) // + QString::fromUtf8(fmpe.mTitle.c_str())); else return QVariant(QString::fromUtf8(fmpe.mTitle.c_str())); diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumModel.h b/retroshare-gui/src/gui/gxsforums/GxsForumModel.h index c69013c3e..10248101f 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumModel.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumModel.h @@ -22,6 +22,7 @@ #include "retroshare/rsgxsifacetypes.h" #include #include +#include struct ForumModelPostEntry: public ForumPostEntry { @@ -76,6 +77,7 @@ public: QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; static const QString FilterString ; + void setFont(const QFont &font); std::vector > getPostVersions(const RsGxsMessageId& mid) const; @@ -185,6 +187,7 @@ private: QColor mBackgroundColorPinned; QColor mBackgroundColorFiltered; + QFont mFont; friend class const_iterator; }; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index 11d04fdd8..fd293560f 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -321,10 +321,6 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget float f = QFontMetricsF(font()).height()/14.0f ; - QFontMetricsF fontMetrics(ui->threadTreeWidget->font()); - int iconHeight = fontMetrics.height() * 1.4; - ui->threadTreeWidget->setIconSize(QSize(iconHeight, iconHeight)); - /* Set header resize modes and initial section sizes */ QHeaderView * ttheader = ui->threadTreeWidget->header () ; @@ -380,6 +376,10 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget [this](std::shared_ptr event) { RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); }, mEventHandlerId, RsEventType::GXS_FORUMS ); + + mFontSizeHandler.registerFontSize(ui->threadTreeWidget, 1.4f, [this](QAbstractItemView *view, int) { + mThreadModel->setFont(view->font()); + }); } void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptr event) diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 322c64fae..8e6b1c01b 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -26,6 +26,7 @@ #include "gui/gxs/GxsMessageFrameWidget.h" #include #include "gui/gxs/GxsIdDetails.h" +#include "util/FontSizeHandler.h" class QSortFilterProxyModel; class QTreeWidgetItem; @@ -234,6 +235,8 @@ private: QSortFilterProxyModel *mThreadProxyModel; QList mSavedExpandedMessages; + FontSizeHandler mFontSizeHandler; + Ui::GxsForumThreadWidget *ui; RsEventsHandlerId_t mEventHandlerId; }; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui index 5a9c51e93..439234047 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.ui @@ -48,10 +48,10 @@ - QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -578,10 +578,9 @@ - ElidedLabel - QLabel -
gui/common/ElidedLabel.h
- 1 + LineEditClear + QLineEdit +
gui/common/LineEditClear.h
GxsIdLabel @@ -589,9 +588,15 @@
gui/gxs/GxsIdLabel.h
- LineEditClear - QLineEdit -
gui/common/LineEditClear.h
+ ElidedLabel + QLabel +
gui/common/ElidedLabel.h
+ 1 +
+ + SubscribeToolButton + QToolButton +
gui/common/SubscribeToolButton.h
RSImageBlockWidget @@ -609,11 +614,6 @@ QComboBox
gui/common/RSComboBox.h
- - SubscribeToolButton - QToolButton -
gui/common/SubscribeToolButton.h
-
diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index de468d270..473fd4844 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -208,6 +208,7 @@ images/logo/logo_info.png images/logo/logo_splash.png images/logo/logo_web_nobackground.png + images/logo/logo_web_nobackground_black.png images/mail-signed.png images/mail-signature-unknown.png images/mailforward24-hover.png diff --git a/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png b/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png new file mode 100644 index 000000000..1be6fbdc0 Binary files /dev/null and b/retroshare-gui/src/gui/images/logo/logo_web_nobackground_black.png differ diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 4e0219b0c..0ee408685 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -299,7 +299,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) QFontDatabase db; foreach(int size, db.standardSizes()) - ui.comboSize->addItem(QString::number(size)); + ui.comboSize->addItem(QString::number(size), size); QStyleOptionComboBox opt; QSize sh; opt.initFrom(ui.comboSize); @@ -408,6 +408,10 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WindowFlags flags) ui.hashBox->setDropWidget(this); ui.hashBox->setAutoHide(true); + mMessageFontSizeHandler.registerFontSize(ui.msgText, [this, db] (QWidget*, int fontSize) { + ui.comboSize->setCurrentIndex(ui.comboSize->findData(fontSize)); + }); + #if QT_VERSION < 0x040700 // embedded images are not supported before QT 4.7.0 ui.imagebtn->setVisible(false); diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.h b/retroshare-gui/src/gui/msgs/MessageComposer.h index 040681095..27bf28458 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.h +++ b/retroshare-gui/src/gui/msgs/MessageComposer.h @@ -28,6 +28,7 @@ #include "ui_MessageComposer.h" #include "gui/msgs/MessageInterface.h" +#include "util/FontSizeHandler.h" class QAction; struct RsIdentityDetails; @@ -267,6 +268,8 @@ private: bool has_gxs; bool mAlreadySent; // prevents a Qt bug that calls the same action twice. + MessageFontSizeHandler mMessageFontSizeHandler; + /** Qt Designer generated object */ Ui::MessageComposer ui; diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.ui b/retroshare-gui/src/gui/msgs/MessageComposer.ui index 9b5e8605c..a5ff266d4 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.ui +++ b/retroshare-gui/src/gui/msgs/MessageComposer.ui @@ -349,10 +349,10 @@
- QFrame::Box + QFrame::StyledPanel - QFrame::Sunken + QFrame::Raised @@ -1400,6 +1400,11 @@ border-image: url(:/images/closepressed.png) + + RSComboBox + QComboBox +
gui/common/RSComboBox.h
+
FriendSelectionWidget QWidget @@ -1411,21 +1416,16 @@ border-image: url(:/images/closepressed.png) QComboBox
gui/gxs/GxsIdChooser.h
- - HashBox - QScrollArea -
gui/common/HashBox.h
- 1 -
MimeTextEdit QTextEdit
gui/common/MimeTextEdit.h
- RSComboBox - QComboBox -
gui/common/RSComboBox.h
+ HashBox + QScrollArea +
gui/common/HashBox.h
+ 1
diff --git a/retroshare-gui/src/gui/msgs/MessageModel.cpp b/retroshare-gui/src/gui/msgs/MessageModel.cpp index 6116e42b4..dc2f16c7c 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.cpp +++ b/retroshare-gui/src/gui/msgs/MessageModel.cpp @@ -57,6 +57,7 @@ RsMessageModel::RsMessageModel(QObject *parent) mQuickViewFilter = QUICK_VIEW_ALL; mFilterType = FILTER_TYPE_NONE; mFilterStrings.clear(); + mFont = QApplication::font(); } void RsMessageModel::preMods() @@ -209,6 +210,8 @@ QVariant RsMessageModel::data(const QModelIndex &index, int role) const std::cerr << "calling data(" << index << ") role=" << role << std::endl; #endif + int coln = index.column(); + if(!index.isValid()) return QVariant(); @@ -246,11 +249,19 @@ QVariant RsMessageModel::data(const QModelIndex &index, int role) const if(role == Qt::FontRole) { - QFont font ; + QFont font = mFont; font.setBold(fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)); return QVariant(font); } + + if (role == Qt::TextAlignmentRole) + { + if((coln == COLUMN_THREAD_ATTACHMENT)) + return int( Qt::AlignHCenter | Qt::AlignVCenter); + else + return QVariant(); + } #ifdef DEBUG_MESSAGE_MODEL std::cerr << " [ok]" << std::endl; @@ -394,6 +405,15 @@ void RsMessageModel::setFilter(FilterType filter_type, const QStringList& string emit dataChanged(createIndex(0,0),createIndex(rowCount()-1,RsMessageModel::columnCount()-1)); } +void RsMessageModel::setFont(const QFont &font) +{ + mFont = font; + + if (rowCount() > 0) { + emit dataChanged(createIndex(0,0), createIndex(rowCount() - 1, RsMessageModel::columnCount() - 1)); + } +} + QVariant RsMessageModel::toolTipRole(const Rs::Msgs::MsgInfoSummary& fmpe,int column) const { if(column == COLUMN_THREAD_AUTHOR || column == COLUMN_THREAD_TO) @@ -430,7 +450,7 @@ QVariant RsMessageModel::backgroundRole(const Rs::Msgs::MsgInfoSummary &/*fmpe*/ QVariant RsMessageModel::sizeHintRole(int col) const { - float factor = QFontMetricsF(QApplication::font()).height()/14.0f ; + float factor = QFontMetricsF(mFont).height()/14.0f ; switch(col) { diff --git a/retroshare-gui/src/gui/msgs/MessageModel.h b/retroshare-gui/src/gui/msgs/MessageModel.h index d23b21f86..3bbd6ee31 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.h +++ b/retroshare-gui/src/gui/msgs/MessageModel.h @@ -22,6 +22,7 @@ #include #include +#include #include "retroshare/rsmsgs.h" @@ -104,6 +105,7 @@ public: void setQuickViewFilter(QuickViewFilter fn) ; void setFilter(FilterType filter_type, const QStringList& strings) ; + void setFont(const QFont &font); int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -184,6 +186,7 @@ private: QuickViewFilter mQuickViewFilter ; QStringList mFilterStrings; FilterType mFilterType; + QFont mFont; std::vector mMessages; std::map mMessagesMap; diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.ui b/retroshare-gui/src/gui/msgs/MessageWidget.ui index de580d7e5..cd4a7c401 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.ui +++ b/retroshare-gui/src/gui/msgs/MessageWidget.ui @@ -6,7 +6,7 @@ 0 0 - 698 + 738 539
@@ -59,11 +59,6 @@ 0 - - - 9 - - Qt::LeftToRight @@ -211,11 +206,6 @@ 0 - - - 9 - - Tags: @@ -232,11 +222,6 @@ 0 - - - 9 - - Subject: @@ -253,11 +238,6 @@ 0 - - - 9 - - Cc: @@ -277,11 +257,6 @@ 0 - - - 9 - - Bcc: @@ -298,11 +273,6 @@ 0 - - - 9 - - To: @@ -321,7 +291,6 @@ - 9 75 true @@ -373,11 +342,6 @@ 16777215 - - - 9 - - true @@ -416,11 +380,6 @@ 0 - - - 9 - - From: @@ -860,8 +819,8 @@ - + diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp index be9eedf6b..7cddc1b7d 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp @@ -306,6 +306,23 @@ MessagesDialog::MessagesDialog(QWidget *parent) mTagEventHandlerId = 0; rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleTagEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_TAG ); + + mFontSizeHandler.registerFontSize(ui.listWidget, 1.5f, [this] (QAbstractItemView*, int fontSize) { + // Set new font size on all items + QList rows; + rows << ROW_INBOX << ROW_OUTBOX << ROW_DRAFTBOX; + + foreach (int row, rows) { + QListWidgetItem *item = ui.listWidget->item(row); + QFont font = item->font(); + font.setPointSize(fontSize); + item->setFont(font); + } + }); + mFontSizeHandler.registerFontSize(ui.quickViewWidget, 1.5f); + mFontSizeHandler.registerFontSize(ui.messageTreeWidget, 1.5f, [this] (QAbstractItemView *view, int) { + mMessageModel->setFont(view->font()); + }); } void MessagesDialog::handleEvent_main_thread(std::shared_ptr event) @@ -511,7 +528,7 @@ void MessagesDialog::fillQuickView() ui.quickViewWidget->clear(); // add static items - item = new QListWidgetItem(tr("Stared"), ui.quickViewWidget); + item = new QListWidgetItem(tr("Starred"), ui.quickViewWidget); item->setIcon(FilesDefs::getIconFromQtResourcePath(IMAGE_STAR_ON)); item->setData(ROLE_QUICKVIEW_TYPE, QUICKVIEW_TYPE_STATIC); item->setData(ROLE_QUICKVIEW_ID, QUICKVIEW_STATIC_ID_STARRED); @@ -1296,7 +1313,7 @@ void MessagesDialog::updateMessageSummaryList() /* calculating the new messages */ std::list msgList; - rsMail->getMessageSummaries(mMessageModel->currentBox(),msgList); + rsMail->getMessageSummaries(Rs::Msgs::BoxName::BOX_ALL,msgList); QMap tagCount; diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.h b/retroshare-gui/src/gui/msgs/MessagesDialog.h index 1d10137c2..7f9573f81 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.h +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.h @@ -25,6 +25,7 @@ #include #include +#include "util/FontSizeHandler.h" #include "ui_MessagesDialog.h" @@ -166,6 +167,8 @@ private: RsEventsHandlerId_t mEventHandlerId; RsEventsHandlerId_t mTagEventHandlerId; + + FontSizeHandler mFontSizeHandler; }; #endif diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.ui b/retroshare-gui/src/gui/msgs/MessagesDialog.ui index 5f1d83eca..516511265 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.ui +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.ui @@ -139,11 +139,6 @@ 0 - - - 11 - - Qt::CustomContextMenu @@ -253,11 +248,6 @@ 0 - - - 11 - -
@@ -375,11 +365,6 @@ Qt::Vertical - - - 10 - - Qt::CustomContextMenu @@ -466,7 +451,7 @@ LineEditClear QLineEdit -
gui/common/LineEditClear.h
+
gui/common/LineEditClear.h
RSTabWidget diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss index df6b9d51c..40fe0b78c 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss @@ -231,7 +231,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox --------------------------------------------------------------------------- */ QGroupBox { font-weight: bold; - border: 1px solid #C9CDD0; + border: 1px solid #C0C4C8; border-radius: 4px; padding: 2px; margin-top: 6px; @@ -1234,7 +1234,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox --------------------------------------------------------------------------- */ QComboBox { - border: 1px solid #C9CDD0; + border: 1px solid #C0C4C8; border-radius: 4px; selection-background-color: #9FCBFF; padding-left: 4px; @@ -1250,7 +1250,7 @@ QComboBox { } QComboBox QAbstractItemView { - border: 1px solid #C9CDD0; + border: 1px solid #C0C4C8; border-radius: 0; background-color: #FAFAFA; selection-background-color: #9FCBFF; @@ -1263,7 +1263,7 @@ QComboBox QAbstractItemView:hover { QComboBox QAbstractItemView:selected { background: #9FCBFF; - color: #C9CDD0; + color: #C0C4C8; } QComboBox QAbstractItemView:alternate { @@ -1301,6 +1301,18 @@ QComboBox::indicator:alternate { background: #FAFAFA; } +QComboBox::item { + /* Remove to fix #282, #285 and MR #288*/ + /*&:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + */ +} + QComboBox::item:alternate { background: #FAFAFA; } @@ -1433,14 +1445,14 @@ QLineEdit { padding-left: 4px; padding-right: 4px; border-style: solid; - border: 1px solid #C9CDD0; + border: 1px solid #C0C4C8; border-radius: 4px; color: #19232D; } QLineEdit:disabled { background-color: #FAFAFA; - color: #788D9C; + color: #9DA9B5; } QLineEdit:hover { @@ -2151,12 +2163,12 @@ QSplitter::handle:hover { } QSplitter::handle:horizontal { - width: 5px; + width: 2px; image: url(":/standard_light/rc/line_vertical.png"); } QSplitter::handle:vertical { - height: 5px; + height: 2px; image: url(":/standard_light/rc/line_horizontal.png"); } @@ -2350,51 +2362,6 @@ QFrame#titleBarFrame QTextEdit { background: white; } -/**** Special Page tweak ****/ - - -/* ConnectFriendWizard */ - -ConnectFriendWizard QPlainTextEdit#friendCertEdit { - border: none; - background: white; - color: black; -} - -ConnectFriendWizard QFrame#friendFrame { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; -} - -ConnectFriendWizard QWizardPage#ConclusionPage > QGroupBox#peerDetailsFrame { - border: 2px solid #039bd5; - border-radius:6px; - background: white; - color: black; - padding: 12 12px; -} - -ConnectFriendWizard QGroupBox::title#peerDetailsFrame -{ - padding: 4 12px; - background: transparent; - padding: 4 12px; - background: #039bd5; - color: white; -} - - -/* GetStartedDialog */ - -GetStartedDialog QTextEdit { - border: 1px solid #B8B6B1; - border-radius: 6px; - background: white; - color: black; -} - - /* HomePage */ HomePage QLabel#userCertLabel { @@ -2509,7 +2476,7 @@ GxsGroupDialog QLabel#groupLogo{ /* Settings */ -PluginItem > QFrame#pluginFrame { +PluginItem QFrame#pluginFrame { border: 2px solid #A8B8D1; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FCFDFE, stop: 1 #E2E8EF); border-radius: 0px @@ -2521,7 +2488,7 @@ PluginItem QLabel#infoLabel { /* Feeds */ -AttachFileItem > QFrame#frame { +AttachFileItem QFrame#frame { border: 2px solid black; background: white; } @@ -2627,88 +2594,78 @@ BoardPostDisplayWidget_card QLabel#siteBoldLabel { color: #787c7e; } +/* GenCertDialog + Change colors here because GUI is not started yet so no user StyleSheet loads */ -/* MessengerWindow */ - -MessengerWindow QFrame#messengerframetop{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #9BDBF9, stop:1 #1592CD); - border: 0px; +GenCertDialog QFrame#profileframe{ + border-image: url(:/images/logo/background.png) 0 0 0 0 stretch stretch; + border-width: 0px; } - -/*************** Optional ***************/ - -/**** WikiPoos ****/ -WikiEditDialog QPushButton#pushButton_History { - color: white; - background: #5bb62b; - border-radius: 4px; - max-height: 20px; - min-width: 4em; - padding: 2px; - padding-left: 6px; - padding-right: 6px; -} - -WikiEditDialog QPushButton#pushButton_History:hover { - background: #57af29; -} - - -/**** The Wire ****/ - -WireGroupItem QFrame#wire_frame:hover { - background-color: #7ecbfb; -} -WireGroupItem QFrame#wire_frame > QLabel { +GenCertDialog QFrame#profileframe QCheckBox, +GenCertDialog QFrame#profileframe QLabel { background: transparent; } -PulseTopLevel QFrame#plainFrame, -PulseViewGroup QFrame#plainFrame, -PulseReply QFrame#plainFrame { - border: 2px solid #c4cfd6; - background: white; +GenCertDialog QLabel#info_Label:enabled { + color: black; + border: 1px solid #DCDC41; + border-radius: 6px; + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); } -PulseAddDialog QTextEdit#textEdit_Pulse { - border: 2px solid #c4cfd6; +GenCertDialog QGroupBox#groupBox, +GenCertDialog QGroupBox#profile_groupBox { + background: rgba(0,0,0,10%); +} +GenCertDialog QGroupBox#profile_groupBox QComboBox, +GenCertDialog QGroupBox#profile_groupBox QSpinBox, +GenCertDialog QGroupBox#profile_groupBox QLineEdit, +GenCertDialog QComboBox#genPGPuser { + border: 2px solid #0099cc; border-radius: 6px; background: white; color: black; } -PulseReply #line_replyLine, -PulseMessage #line{ - color: #c4cfd6; +GenCertDialog QPushButton#genButton { + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +GenCertDialog QPushButton#genButton:hover { + border-image: url(:/images/btn_blue_hover.png) 4; +} +GenCertDialog QPushButton#genButton:disabled { + border-image: url(:/images/btn_27.png) 4; + color: black; } -PulseReply QLabel#label_groupName{ - color: #5b7083; +/* StartDialog + To get the same style for all user and not use last connected one. */ + +StartDialog QFrame#loginframe{ + border-image: url(:/images/logo/background_lessblue.png) 0 0 0 0 stretch stretch; + border-width: 0px; } -PulseReplySeperator QFrame#frame { - border: 2px solid #CCCCCC; - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #EEEEEE, stop: 1 #CCCCCC); - border-radius: 10px} +StartDialog QFrame#loginframe QCheckBox, +StartDialog QFrame#loginframe QLabel { + background: transparent; +} +StartDialog QGroupBox#profilGBox { + background: rgba(0,0,0,10%); + border-radius: 3px; + border-width: 0px; } -QLabel#label_masthead{ - border: 2px solid #CCCCCC; - border-radius: 4px; +StartDialog QPushButton#loadButton { + background: transparent; + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; } - -/**** PhotoShare ****/ -AlbumItem QFrame#albumFrame { - border: 2px solid #CCCCCC; - border-radius: 10px -} - -PhotoItem QFrame#photoFrame { - border: 2px solid #CCCCCC; - border-radius: 10px -} - -PhotoItem QWidget:hover { - background-color: #7ecbfb; +StartDialog QPushButton#loadButton:hover { + background: transparent; + border-image: url(:/images/btn_blue_hover.png) 4; } diff --git a/retroshare-gui/src/gui/qss/stylesheet/default.qss b/retroshare-gui/src/gui/qss/stylesheet/default.qss index defcc82f8..4b8d1645f 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/default.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/default.qss @@ -141,88 +141,6 @@ QLabel#newLabel:enabled { } -/* StartDialog - To get the same style for all user and not use last connected one. */ - -StartDialog QFrame#loginframe{ - border-image: url(:/images/logo/background_lessblue.png) 0 0 0 0 stretch stretch; - border-width: 0px; -} -StartDialog QFrame#loginframe QCheckBox, -StartDialog QFrame#loginframe QLabel { - background: transparent; -} -StartDialog QGroupBox#profilGBox { - background: rgba(0,0,0,10%); - border-radius: 3px; - border-width: 0px; -} - -StartDialog QGroupBox#profilGBox * { - background-color: white; - color: black; -} - -StartDialog QPushButton#loadButton { - background: transparent; - border-image: url(:/images/btn_blue.png) 4; - border-width: 4; - color: white; -} -StartDialog QPushButton#loadButton:hover { - background: transparent; - border-image: url(:/images/btn_blue_hover.png) 4; -} - - - -/* GenCertDialog - Change colors here because GUI is not started yet so no user StyleSheet loads */ - -GenCertDialog QFrame#profileframe{ - border-image: url(:/images/logo/background.png) 0 0 0 0 stretch stretch; - border-width: 0px; -} -GenCertDialog QFrame#profileframe QCheckBox, -GenCertDialog QFrame#profileframe QLabel { - background: transparent; -} - -GenCertDialog QLabel#info_Label:enabled { - color: black; - border: 1px solid #DCDC41; - border-radius: 6px; - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2); -} - -GenCertDialog QGroupBox#groupBox, -GenCertDialog QGroupBox#profile_groupBox { - background: rgba(0,0,0,10%); -} -GenCertDialog QGroupBox#profile_groupBox QComboBox, -GenCertDialog QGroupBox#profile_groupBox QSpinBox, -GenCertDialog QGroupBox#profile_groupBox QLineEdit, -GenCertDialog QComboBox#genPGPuser { - border: 2px solid #0099cc; - border-radius: 6px; - background: white; - color: black; -} - -GenCertDialog QPushButton#genButton { - border-image: url(:/images/btn_blue.png) 4; - border-width: 4; - color: white; -} -GenCertDialog QPushButton#genButton:hover { - border-image: url(:/images/btn_blue_hover.png) 4; -} -GenCertDialog QPushButton#genButton:disabled { - border-image: url(:/images/btn_27.png) 4; - color: black; -} - - /* AvatarWidget */ AvatarWidget{border-width: 10px;} @@ -418,3 +336,27 @@ OpModeStatus[opMode="Minimal"] { [WrongValue="true"] { background-color: #FF8080; } + +GenCertDialog QPushButton#genButton { + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +GenCertDialog QPushButton#genButton:hover { + border-image: url(:/images/btn_blue_hover.png) 4; +} +GenCertDialog QPushButton#genButton:disabled { + border-image: url(:/images/btn_27.png) 4; + color: black; +} + +StartDialog QPushButton#loadButton { + background: transparent; + border-image: url(:/images/btn_blue.png) 4; + border-width: 4; + color: white; +} +StartDialog QPushButton#loadButton:hover { + background: transparent; + border-image: url(:/images/btn_blue_hover.png) 4; +} diff --git a/retroshare-gui/src/gui/settings/AppearancePage.cpp b/retroshare-gui/src/gui/settings/AppearancePage.cpp index a96df209d..2aecd6024 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.cpp +++ b/retroshare-gui/src/gui/settings/AppearancePage.cpp @@ -101,6 +101,9 @@ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) connect(ui.mainPageButtonType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRbtPageOnToolBar() )); // connect(ui.menuItemsButtonType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(updateActionButtonLoc() )); + + connect(ui.minimumFontSize_SB, SIGNAL(valueChanged(int)), this, SLOT(updateFontSize())) ; + } void AppearancePage::switch_status_grpStatus(bool b) { switch_status(MainWindow::StatusGrpStatus ,"ShowStatusBar", b) ; } @@ -359,4 +362,12 @@ void AppearancePage::load() whileBlocking(ui.checkBoxShowToasterDisable)->setChecked(Settings->valueFromGroup("StatusBar", "ShowToaster", QVariant(true)).toBool()); whileBlocking(ui.checkBoxShowSystrayOnStatus)->setChecked(Settings->valueFromGroup("StatusBar", "ShowSysTrayOnStatusBar", QVariant(false)).toBool()); + whileBlocking(ui.minimumFontSize_SB)->setValue(Settings->getFontSize()); +} + +void AppearancePage::updateFontSize() +{ + Settings->setFontSize(ui.minimumFontSize_SB->value()); + + NotifyQt::getInstance()->notifySettingsChanged(); } diff --git a/retroshare-gui/src/gui/settings/AppearancePage.h b/retroshare-gui/src/gui/settings/AppearancePage.h index 897563753..741bd752e 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.h +++ b/retroshare-gui/src/gui/settings/AppearancePage.h @@ -71,6 +71,8 @@ private slots: // void updateCmboListItemSize(); void updateStyle() ; + void updateFontSize(); + private: void switch_status(MainWindow::StatusElement s,const QString& key,bool b); diff --git a/retroshare-gui/src/gui/settings/AppearancePage.ui b/retroshare-gui/src/gui/settings/AppearancePage.ui index 96e5effe8..13dc7a48e 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.ui +++ b/retroshare-gui/src/gui/settings/AppearancePage.ui @@ -14,22 +14,7 @@ Qt::NoContextMenu - - 6 - - - 6 - - - 6 - - - 6 - - - 0 - - + @@ -86,110 +71,12 @@
- - - - - 0 - 64 - - - - Qt::NoContextMenu - - - - - - Style - - - - - - - 150 - 0 - - - - Choose RetroShare's interface style - - - - - - - Qt::Horizontal - - - - 215 - 20 - - - - - - - - - - - - 0 - 64 - - - - Style Sheet - - - - - - - 150 - 0 - - - - - - - - Qt::Horizontal - - - - 215 - 20 - - - - - - - - - - - Qt::Vertical - - - - 361 - 61 - - - - - + 0 - 228 + 0 @@ -198,8 +85,8 @@ Tool Bar - - + + @@ -237,7 +124,7 @@ - + @@ -289,19 +176,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -352,10 +226,79 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + - + + + + Fonts + + + + + + + + Minimum font size + + + + + + + 5 + + + 64 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 188 + 96 + + + + + + + + Status Bar @@ -464,6 +407,104 @@ + + + + Qt::Vertical + + + + 361 + 61 + + + + + + + + + 0 + 64 + + + + Qt::NoContextMenu + + + + + + Style + + + + + + + 150 + 0 + + + + Choose RetroShare's interface style + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + + + + + + + 0 + 64 + + + + Style Sheet + + + + + + + 150 + 0 + + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + + diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.cc b/retroshare-gui/src/gui/settings/JsonApiPage.cc index 2b7f25d80..ace092e0c 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.cc +++ b/retroshare-gui/src/gui/settings/JsonApiPage.cc @@ -232,23 +232,23 @@ void JsonApiPage::addTokenClicked() whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); } -void JsonApiPage::removeTokenClicked() -{ - QString token(ui.tokenLineEdit->text()); - rsJsonApi->revokeAuthToken(token.toStdString()); - - QStringList newTk; - - for(const auto& it : rsJsonApi->getAuthorizedTokens()) - newTk.push_back( - QString::fromStdString(it.first) + ":" + - QString::fromStdString(it.second) ); - - whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()) ); -} - +void JsonApiPage::removeTokenClicked() +{ + QString token(ui.tokenLineEdit->text()); + std::string tokenStr = token.toStdString(); + rsJsonApi->revokeAuthToken(tokenStr.substr(0, tokenStr.find_first_of(":"))); + + QStringList newTk; + + for(const auto& it : rsJsonApi->getAuthorizedTokens()) + newTk.push_back( + QString::fromStdString(it.first) + ":" + + QString::fromStdString(it.second) ); + + whileBlocking(ui.tokensListView)->setModel(new QStringListModel(Settings->getJsonApiAuthTokens()) ); +} + void JsonApiPage::tokenClicked(const QModelIndex& index) { ui.tokenLineEdit->setText(ui.tokensListView->model()->data(index).toString()); } - diff --git a/retroshare-gui/src/gui/settings/MessagePage.cpp b/retroshare-gui/src/gui/settings/MessagePage.cpp index ff302317d..be8b515ff 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.cpp +++ b/retroshare-gui/src/gui/settings/MessagePage.cpp @@ -18,6 +18,8 @@ * * *******************************************************************************/ +#include + #include "rshare.h" #include "rsharesettings.h" #include "retroshare/rsmsgs.h" @@ -28,6 +30,7 @@ #include #include "NewTag.h" #include "util/qtthreadsutils.h" +#include "gui/notifyqt.h" MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) : ConfigPage(parent, flags) @@ -48,13 +51,20 @@ MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) ui.openComboBox->addItem(tr("A new tab"), RshareSettings::MSG_OPEN_TAB); ui.openComboBox->addItem(tr("A new window"), RshareSettings::MSG_OPEN_WINDOW); - + + // Font size + QFontDatabase db; + foreach(int size, db.standardSizes()) { + ui.minimumFontSize->addItem(QString::number(size), size); + } + connect(ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(distantMsgsComboBoxChanged(int))); connect(ui.setMsgToReadOnActivate,SIGNAL(toggled(bool)), this,SLOT(updateMsgToReadOnActivate())); connect(ui.loadEmbeddedImages, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmbededImages() )); connect(ui.openComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(updateMsgOpen() )); connect(ui.emoticonscheckBox, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmoticons() )); + connect(ui.minimumFontSize, SIGNAL(activated(QString)), this, SLOT(updateFontSize())) ; mTagEventHandlerId = 0; rsEvents->registerEventsHandler( [this](std::shared_ptr event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mTagEventHandlerId, RsEventType::MAIL_TAG ); @@ -116,12 +126,11 @@ void MessagePage::updateMsgTags() void MessagePage::load() { - Settings->beginGroup(QString("Messages")); whileBlocking(ui.setMsgToReadOnActivate)->setChecked(Settings->getMsgSetToReadOnActivate()); whileBlocking(ui.loadEmbeddedImages)->setChecked(Settings->getMsgLoadEmbeddedImages()); whileBlocking(ui.openComboBox)->setCurrentIndex(ui.openComboBox->findData(Settings->getMsgOpen())); whileBlocking(ui.emoticonscheckBox)->setChecked(Settings->value("Emoticons", true).toBool()); - Settings->endGroup(); + whileBlocking(ui.minimumFontSize)->setCurrentIndex(ui.minimumFontSize->findData(Settings->getMessageFontSize())); // state of filter combobox @@ -298,3 +307,9 @@ void MessagePage::currentRowChangedTag(int row) ui.deletepushButton->setEnabled(bDeleteEnable); } +void MessagePage::updateFontSize() +{ + Settings->setMessageFontSize(ui.minimumFontSize->currentData().toInt()); + + NotifyQt::getInstance()->notifySettingsChanged(); +} diff --git a/retroshare-gui/src/gui/settings/MessagePage.h b/retroshare-gui/src/gui/settings/MessagePage.h index 774d31b95..c5b9f7544 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.h +++ b/retroshare-gui/src/gui/settings/MessagePage.h @@ -60,6 +60,7 @@ private slots: void updateDistantMsgs() ; void updateMsgTags() ; void updateLoadEmoticons(); + void updateFontSize(); private: void handleEvent_main_thread(std::shared_ptr event); diff --git a/retroshare-gui/src/gui/settings/MessagePage.ui b/retroshare-gui/src/gui/settings/MessagePage.ui index fd55218e8..3e5ab3842 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.ui +++ b/retroshare-gui/src/gui/settings/MessagePage.ui @@ -16,44 +16,15 @@ 0 - - - - - Distant messages: - - - - - - - Everyone - - - - - Contacts - - - - - Nobody - - - - - - - - Accept encrypted distant messages from - - - - - - - + + + + + 0 + 0 + + Reading @@ -65,20 +36,6 @@ - - - - - - Open messages in - - - - - - - - @@ -93,10 +50,24 @@ + + + + + + Open messages in + + + + + + + + - + Tags @@ -172,6 +143,102 @@ + + + + Distant messages: + + + + + + + Everyone + + + + + Contacts + + + + + Nobody + + + + + + + + Accept encrypted distant messages from + + + + + + + + + + + 0 + 0 + + + + Fonts + + + + + + + + Qt::LeftToRight + + + Minimum font size + + + + + + + + MS Sans Serif + 10 + + + + Qt::ClickFocus + + + Font size + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index adb1d655c..be2404bc8 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -228,6 +228,7 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) connect(ui.hiddenpage_proxyPort_tor, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.hiddenpage_proxyAddress_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.hiddenpage_proxyPort_i2p, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); + connect(ui.hiddenpage_localPort, SIGNAL(editingFinished()),this,SLOT(saveAddresses())); connect(ui.totalDownloadRate,SIGNAL(valueChanged(int)),this,SLOT(saveRates())); connect(ui.totalUploadRate, SIGNAL(valueChanged(int)),this,SLOT(saveRates())); @@ -1139,18 +1140,18 @@ void ServerPage::loadHiddenNode() ui.iconlabel_ext->hide(); ui.textlabel_ext->hide(); ui.extPortLabel->hide(); - + ui.ipAddressLabel->hide(); ui.cleanKnownIPs_PB->hide(); - + ui.ipAddressList->hide(); ui.allowIpDeterminationCB->hide(); ui.IPServersLV->hide(); - + ui.textlabel_hiddenMode->show(); ui.iconlabel_hiddenMode->show() ; ui.iconlabel_hiddenMode->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/ledon1.png")); - + // CHANGE OPTIONS ON whileBlocking(ui.discComboBox)->removeItem(3); whileBlocking(ui.discComboBox)->removeItem(2); @@ -1731,8 +1732,9 @@ void ServerPage::saveSam() new_proxyaddr = ui.hiddenpage_proxyAddress_i2p -> text().toStdString(); new_proxyport = ui.hiddenpage_proxyPort_i2p -> value(); - // SAMv3 has no proxy port, everything goes through the SAM port. - if ((new_proxyaddr != orig_proxyaddr) /* || (new_proxyport != orig_proxyport) */) { + // SAMv3 has no proxy port, everything goes through the SAM port. + // Still need to check the proxyport for manual i2p + if ((new_proxyaddr != orig_proxyaddr) || (new_proxyport != orig_proxyport)) { rsPeers->setProxyServer(RS_HIDDEN_TYPE_I2P, new_proxyaddr, new_proxyport); } } diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp index 6a0feaf2b..5b3b49908 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.cpp +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -52,7 +52,7 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ; QObject::connect(ui._max_up_SB,SIGNAL(valueChanged(int)),this,SLOT(updateMaxUploadSlots(int))) ; QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ; - QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ; + //QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ; QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ; QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) ); QObject::connect(ui._filePermDirectDL_CB,SIGNAL(activated(int)),this,SLOT(updateFilePermDirectDL(int))); @@ -112,6 +112,7 @@ void TransferPage::updateMaxUploadSlots(int b) rsFiles->setMaxUploadSlotsPerFriend(b) ; } +#ifdef TO_REMOVE void TransferPage::updateEncryptionPolicy(int b) { switch(b) @@ -123,6 +124,7 @@ void TransferPage::updateEncryptionPolicy(int b) break ; } } +#endif void TransferPage::updateFilePermDirectDL(int i) { @@ -160,11 +162,13 @@ void TransferPage::load() case FileChunksInfo::CHUNK_STRATEGY_RANDOM: whileBlocking(ui._defaultStrategy_CB)->setCurrentIndex(2) ; break ; } +#ifdef TO_REMOVE switch(rsFiles->defaultEncryptionPolicy()) { case RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE: whileBlocking(ui._e2e_encryption_CB)->setCurrentIndex(0) ; break ; case RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT : whileBlocking(ui._e2e_encryption_CB)->setCurrentIndex(1) ; break ; } +#endif whileBlocking(ui._diskSpaceLimit_SB)->setValue(rsFiles->freeDiskSpaceLimit()) ; whileBlocking(ui._max_tr_up_per_sec_SB)->setValue(rsTurtle->getMaxTRForwardRate()) ; diff --git a/retroshare-gui/src/gui/settings/TransferPage.h b/retroshare-gui/src/gui/settings/TransferPage.h index a2a0a1061..077d5a6ec 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.h +++ b/retroshare-gui/src/gui/settings/TransferPage.h @@ -47,7 +47,6 @@ class TransferPage: public ConfigPage void updateDefaultStrategy(int) ; void updateDiskSizeLimit(int) ; void updateMaxTRUpRate(int); - void updateEncryptionPolicy(int); void updateMaxUploadSlots(int); void updateFilePermDirectDL(int); void updateIgnoreLists(); diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui index b6d8cd7ff..4b48be012 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.ui +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -14,7 +14,7 @@ - 1 + 0 @@ -400,13 +400,6 @@ p, li { white-space: pre-wrap; } - - - - End-to-end encryption: - - - @@ -503,23 +496,6 @@ p, li { white-space: pre-wrap; } - - - - <html><head/><body><p>Anonymous tunnels can be end-o-end encrypted. In order to maintain backward compatibility, this can be made optional (choosing &quot;Accepted&quot;), but in the end, all Retroshare nodes will be switched to &quot;Enforced&quot;, meaning that all anonymous transfers will be end-to-end encrypted. With &quot;Accepted&quot;, it is likely that you will transfer using twice as many tunnels, since there is no way to know that an encrypted and a clear tunnel actually transfer from the same source.</p></body></html> - - - - Accepted - - - - - Enforced - - - - diff --git a/retroshare-gui/src/gui/settings/rsettingswin.cpp b/retroshare-gui/src/gui/settings/rsettingswin.cpp index 1d3d4ecc3..a9fab8895 100644 --- a/retroshare-gui/src/gui/settings/rsettingswin.cpp +++ b/retroshare-gui/src/gui/settings/rsettingswin.cpp @@ -93,6 +93,8 @@ SettingsPage::SettingsPage(QWidget *parent) connect(ui.listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(setNewPage(int))); connect(this, SIGNAL(finished(int)), this, SLOT(dialogFinished(int))); + + mFontSizeHandler.registerFontSize(ui.listWidget); } SettingsPage::~SettingsPage() diff --git a/retroshare-gui/src/gui/settings/rsettingswin.h b/retroshare-gui/src/gui/settings/rsettingswin.h index 74fb0d40c..47eb33e4b 100755 --- a/retroshare-gui/src/gui/settings/rsettingswin.h +++ b/retroshare-gui/src/gui/settings/rsettingswin.h @@ -27,6 +27,7 @@ #include #include "ui_settingsw.h" +#include "util/FontSizeHandler.h" class FloatingHelpBrowser; @@ -72,6 +73,8 @@ private: FloatingHelpBrowser *mHelpBrowser; static int lastPage; + FontSizeHandler mFontSizeHandler; + /* UI - from Designer */ Ui::Settings ui; }; diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index e811acd4a..d878d6c99 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -1190,6 +1190,38 @@ void RshareSettings::setPageAlreadyDisplayed(const QString& page_name,bool b) return setValueToGroup("PageAlreadyDisplayed",page_name,b); } +int RshareSettings::getFontSize() +{ +#if defined(Q_OS_DARWIN) + int defaultFontSize = 13; +#else + int defaultFontSize = 11; +#endif + + return value("FontSize", defaultFontSize).toInt(); +} + +void RshareSettings::setFontSize(int value) +{ + setValue("FontSize", value); +} + +int RshareSettings::getMessageFontSize() +{ +#if defined(Q_OS_DARWIN) + int defaultFontSize = 12; +#else + int defaultFontSize = 11; +#endif + + return valueFromGroup("Message", "FontSize", defaultFontSize).toInt(); +} + +void RshareSettings::setMessageFontSize(int value) +{ + setValueToGroup("Message", "FontSize", value); +} + #ifdef RS_JSONAPI bool RshareSettings::getJsonApiEnabled() { diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h index 362e52606..317dedb56 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -343,6 +343,12 @@ public: bool getPageAlreadyDisplayed(const QString& page_code) ; void setPageAlreadyDisplayed(const QString& page_code,bool b) ; + int getFontSize(); + void setFontSize(int value); + + int getMessageFontSize(); + void setMessageFontSize(int value); + #ifdef RS_JSONAPI bool getJsonApiEnabled(); void setJsonApiEnabled(bool enabled); diff --git a/retroshare-gui/src/gui/settings/settingsw.ui b/retroshare-gui/src/gui/settings/settingsw.ui index d1cbd3caf..605e8558e 100644 --- a/retroshare-gui/src/gui/settings/settingsw.ui +++ b/retroshare-gui/src/gui/settings/settingsw.ui @@ -35,11 +35,6 @@ 16777215 - - - 11 - - Qt::IgnoreAction @@ -100,7 +95,6 @@ - 12 75 true @@ -135,8 +129,8 @@ 0 0 - 1313 - 849 + 1264 + 845 diff --git a/retroshare-gui/src/lang/retroshare_bg.ts b/retroshare-gui/src/lang/retroshare_bg.ts index 7bb75556d..c57ad6a7a 100644 --- a/retroshare-gui/src/lang/retroshare_bg.ts +++ b/retroshare-gui/src/lang/retroshare_bg.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_ca_ES.ts b/retroshare-gui/src/lang/retroshare_ca_ES.ts index ef5261f6a..1e88b2136 100644 --- a/retroshare-gui/src/lang/retroshare_ca_ES.ts +++ b/retroshare-gui/src/lang/retroshare_ca_ES.ts @@ -14370,7 +14370,7 @@ Voleu desar el missatge? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_cs.ts b/retroshare-gui/src/lang/retroshare_cs.ts index b0c0c123b..9ddff2a55 100644 --- a/retroshare-gui/src/lang/retroshare_cs.ts +++ b/retroshare-gui/src/lang/retroshare_cs.ts @@ -14334,7 +14334,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_da.ts b/retroshare-gui/src/lang/retroshare_da.ts index ffd7a7c0e..4cb8c0823 100644 --- a/retroshare-gui/src/lang/retroshare_da.ts +++ b/retroshare-gui/src/lang/retroshare_da.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts index b2b9f2ea3..e37c020a9 100644 --- a/retroshare-gui/src/lang/retroshare_de.ts +++ b/retroshare-gui/src/lang/retroshare_de.ts @@ -14360,7 +14360,7 @@ Möchtest du die Nachricht speichern ? - Stared + Starred Markiert diff --git a/retroshare-gui/src/lang/retroshare_el.ts b/retroshare-gui/src/lang/retroshare_el.ts index 82ed18b46..1b43e7f05 100644 --- a/retroshare-gui/src/lang/retroshare_el.ts +++ b/retroshare-gui/src/lang/retroshare_el.ts @@ -14332,7 +14332,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_en.ts b/retroshare-gui/src/lang/retroshare_en.ts index 0f9c08da7..74a7b83b3 100644 --- a/retroshare-gui/src/lang/retroshare_en.ts +++ b/retroshare-gui/src/lang/retroshare_en.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_es.ts b/retroshare-gui/src/lang/retroshare_es.ts index 358668fc3..cc21a60c3 100644 --- a/retroshare-gui/src/lang/retroshare_es.ts +++ b/retroshare-gui/src/lang/retroshare_es.ts @@ -14369,7 +14369,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_fi.ts b/retroshare-gui/src/lang/retroshare_fi.ts index 035f64f23..2a52e18a6 100644 --- a/retroshare-gui/src/lang/retroshare_fi.ts +++ b/retroshare-gui/src/lang/retroshare_fi.ts @@ -14374,7 +14374,7 @@ Haluatko tallentaa viestin? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_fr.ts b/retroshare-gui/src/lang/retroshare_fr.ts index 876414b16..127c0fdd7 100644 --- a/retroshare-gui/src/lang/retroshare_fr.ts +++ b/retroshare-gui/src/lang/retroshare_fr.ts @@ -14385,7 +14385,7 @@ Voulez-vous enregistrer votre message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_hu.ts b/retroshare-gui/src/lang/retroshare_hu.ts index c2e111012..d5967ea59 100644 --- a/retroshare-gui/src/lang/retroshare_hu.ts +++ b/retroshare-gui/src/lang/retroshare_hu.ts @@ -14358,7 +14358,7 @@ Szeretnéd menteni az üzenetet? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_it.ts b/retroshare-gui/src/lang/retroshare_it.ts index 4cfb28a4d..ade137565 100644 --- a/retroshare-gui/src/lang/retroshare_it.ts +++ b/retroshare-gui/src/lang/retroshare_it.ts @@ -14352,7 +14352,7 @@ ricerca - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_ja_JP.ts b/retroshare-gui/src/lang/retroshare_ja_JP.ts index 89bf9c9f2..5f2256dd5 100644 --- a/retroshare-gui/src/lang/retroshare_ja_JP.ts +++ b/retroshare-gui/src/lang/retroshare_ja_JP.ts @@ -14304,7 +14304,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_ko.ts b/retroshare-gui/src/lang/retroshare_ko.ts index 8867098a1..927baa9e7 100644 --- a/retroshare-gui/src/lang/retroshare_ko.ts +++ b/retroshare-gui/src/lang/retroshare_ko.ts @@ -14312,7 +14312,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_nl.ts b/retroshare-gui/src/lang/retroshare_nl.ts index 6d7c25195..bb4fef66a 100644 --- a/retroshare-gui/src/lang/retroshare_nl.ts +++ b/retroshare-gui/src/lang/retroshare_nl.ts @@ -14331,7 +14331,7 @@ Wil je het bericht bewaren? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_pl.ts b/retroshare-gui/src/lang/retroshare_pl.ts index 46abcec56..637121e24 100644 --- a/retroshare-gui/src/lang/retroshare_pl.ts +++ b/retroshare-gui/src/lang/retroshare_pl.ts @@ -14434,7 +14434,7 @@ Czy chcesz zapisać wiadomość ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_pt.ts b/retroshare-gui/src/lang/retroshare_pt.ts index a760d3920..842fde2d7 100644 --- a/retroshare-gui/src/lang/retroshare_pt.ts +++ b/retroshare-gui/src/lang/retroshare_pt.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_ru.ts b/retroshare-gui/src/lang/retroshare_ru.ts index 197a77c4f..20b2f9e16 100644 --- a/retroshare-gui/src/lang/retroshare_ru.ts +++ b/retroshare-gui/src/lang/retroshare_ru.ts @@ -14373,7 +14373,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_sl.ts b/retroshare-gui/src/lang/retroshare_sl.ts index bb6973983..581ac731c 100644 --- a/retroshare-gui/src/lang/retroshare_sl.ts +++ b/retroshare-gui/src/lang/retroshare_sl.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_sr.ts b/retroshare-gui/src/lang/retroshare_sr.ts index 208c6f3e6..01e51db3d 100644 --- a/retroshare-gui/src/lang/retroshare_sr.ts +++ b/retroshare-gui/src/lang/retroshare_sr.ts @@ -14304,7 +14304,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_sv.ts b/retroshare-gui/src/lang/retroshare_sv.ts index ee425491b..754e79479 100644 --- a/retroshare-gui/src/lang/retroshare_sv.ts +++ b/retroshare-gui/src/lang/retroshare_sv.ts @@ -14332,7 +14332,7 @@ Vill du spara meddelandet? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_tr.ts b/retroshare-gui/src/lang/retroshare_tr.ts index cd2651115..1163f7149 100644 --- a/retroshare-gui/src/lang/retroshare_tr.ts +++ b/retroshare-gui/src/lang/retroshare_tr.ts @@ -14374,7 +14374,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_zh_CN.ts b/retroshare-gui/src/lang/retroshare_zh_CN.ts index d35ab9a92..82bafc9e1 100644 --- a/retroshare-gui/src/lang/retroshare_zh_CN.ts +++ b/retroshare-gui/src/lang/retroshare_zh_CN.ts @@ -14361,7 +14361,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/lang/retroshare_zh_TW.ts b/retroshare-gui/src/lang/retroshare_zh_TW.ts index d81166627..2acc19ab2 100644 --- a/retroshare-gui/src/lang/retroshare_zh_TW.ts +++ b/retroshare-gui/src/lang/retroshare_zh_TW.ts @@ -14303,7 +14303,7 @@ Do you want to save message ? - Stared + Starred diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index d73117b84..6f217db9c 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -451,6 +451,7 @@ HEADERS += rshare.h \ util/qtthreadsutils.h \ util/ClickableLabel.h \ util/AspectRatioPixmapLabel.h \ + util/FontSizeHandler.h \ gui/profile/ProfileWidget.h \ gui/profile/ProfileManager.h \ gui/profile/StatusMessage.h \ @@ -817,6 +818,7 @@ SOURCES += main.cpp \ util/RichTextEdit.cpp \ util/ClickableLabel.cpp \ util/AspectRatioPixmapLabel.cpp \ + util/FontSizeHandler.cpp \ gui/profile/ProfileWidget.cpp \ gui/profile/StatusMessage.cpp \ gui/profile/ProfileManager.cpp \ @@ -1257,6 +1259,7 @@ identities { HEADERS += \ gui/Identity/IdDialog.h \ + gui/Identity/IdentityListModel.h \ gui/Identity/IdEditDialog.h \ gui/Identity/IdDetailsDialog.h \ @@ -1266,6 +1269,7 @@ identities { SOURCES += \ gui/Identity/IdDialog.cpp \ + gui/Identity/IdentityListModel.cpp \ gui/Identity/IdEditDialog.cpp \ gui/Identity/IdDetailsDialog.cpp \ diff --git a/retroshare-gui/src/util/FontSizeHandler.cpp b/retroshare-gui/src/util/FontSizeHandler.cpp new file mode 100644 index 000000000..c184da0de --- /dev/null +++ b/retroshare-gui/src/util/FontSizeHandler.cpp @@ -0,0 +1,210 @@ +/******************************************************************************* + * util/FontSizeHandler.cpp * + * * + * Copyright (C) 2025, Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include +#include +#include + +#include "rshare.h" +#include "FontSizeHandler.h" +#include "gui/settings/rsharesettings.h" +#include "gui/notifyqt.h" + +// Data for QAbstractItemView +struct FontSizeHandlerWidgetData +{ + std::function callback; +}; + +// Data for QWidget +struct FontSizeHandlerViewData +{ + float iconHeightFactor; + std::function callback; +}; + +class FontSizeHandlerObject : public QObject +{ +public: + FontSizeHandlerObject(FontSizeHandlerBase *fontSizeHandler): QObject() + { + mFontSizeHandlerBase = fontSizeHandler; + } + + bool eventFilter(QObject* object, QEvent* event) + { + if (event->type() == QEvent::StyleChange) { + QMap::iterator itView = mView.find((QAbstractItemView*) object); + if (itView != mView.end()) { + mFontSizeHandlerBase->updateFontSize(itView.key(), itView.value().iconHeightFactor, itView.value().callback); + } + + QMap::iterator itWidget = mWidget.find((QWidget*) object); + if (itWidget != mWidget.end()) { + mFontSizeHandlerBase->updateFontSize(itWidget.key(), itWidget.value().callback); + } + } + + return false; + } + + void registerFontSize(QWidget *widget, std::function callback) + { + FontSizeHandlerWidgetData data; + data.callback = callback; + mWidget.insert(widget, data); + + QObject::connect(NotifyQt::getInstance(), &NotifyQt::settingsChanged, widget, [this, widget, callback]() { + mFontSizeHandlerBase->updateFontSize(widget, callback); + }); + + widget->installEventFilter(this); + QObject::connect(widget, &QObject::destroyed, this, [this, widget](QObject *object) { + if (widget == object) { + mWidget.remove(widget); + widget->removeEventFilter(this); + } + }); + + mFontSizeHandlerBase->updateFontSize(widget, callback, true); + } + + void registerFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback) + { + FontSizeHandlerViewData data; + data.iconHeightFactor = iconHeightFactor; + data.callback = callback; + mView.insert(view, data); + + QObject::connect(NotifyQt::getInstance(), &NotifyQt::settingsChanged, view, [this, view, iconHeightFactor, callback]() { + mFontSizeHandlerBase->updateFontSize(view, iconHeightFactor, callback); + }); + + view->installEventFilter(this); + QObject::connect(view, &QObject::destroyed, this, [this, view](QObject *object) { + if (view == object) { + mView.remove(view); + view->removeEventFilter(this); + } + }); + + mFontSizeHandlerBase->updateFontSize(view, iconHeightFactor, callback, true); + } + +private: + FontSizeHandlerBase *mFontSizeHandlerBase; + QMap mView; + QMap mWidget; +}; + +FontSizeHandlerBase::FontSizeHandlerBase(Type type) +{ + mType = type; + mObject = nullptr; +} + +FontSizeHandlerBase::~FontSizeHandlerBase() +{ + if (mObject) { + mObject->deleteLater(); + mObject = nullptr; + } +} + +int FontSizeHandlerBase::getFontSize() +{ + switch (mType) { + case FONT_SIZE: + return Settings->getFontSize(); + + case MESSAGE_FONT_SIZE: + return Settings->getMessageFontSize(); + } + + return 0; +} + +void FontSizeHandlerBase::registerFontSize(QWidget *widget, std::function callback) +{ + if (!widget) { + return; + } + + if (!mObject) { + mObject = new FontSizeHandlerObject(this); + } + + mObject->registerFontSize(widget, callback); +} + +void FontSizeHandlerBase::registerFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback) +{ + if (!view) { + return; + } + + if (!mObject) { + mObject = new FontSizeHandlerObject(this); + } + + mObject->registerFontSize(view, iconHeightFactor, callback); +} + +void FontSizeHandlerBase::updateFontSize(QWidget *widget, std::function callback, bool force) +{ + if (!widget) { + return; + } + + int fontSize = getFontSize(); + QFont font = widget->font(); + if (force || font.pointSize() != fontSize) { + font.setPointSize(fontSize); + widget->setFont(font); + + if (callback) { + callback(widget, fontSize); + } + } +} + +void FontSizeHandlerBase::updateFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback, bool force) +{ + if (!view) { + return; + } + + int fontSize = getFontSize(); + QFont font = view->font(); + if (force || font.pointSize() != fontSize) { + font.setPointSize(fontSize); + view->setFont(font); + + if (iconHeightFactor) { + QFontMetricsF fontMetrics(font); + int iconHeight = fontMetrics.height() * iconHeightFactor; + view->setIconSize(QSize(iconHeight, iconHeight)); + } + + if (callback) { + callback(view, fontSize); + } + } +} diff --git a/retroshare-gui/src/util/FontSizeHandler.h b/retroshare-gui/src/util/FontSizeHandler.h new file mode 100644 index 000000000..bf9c8058b --- /dev/null +++ b/retroshare-gui/src/util/FontSizeHandler.h @@ -0,0 +1,73 @@ +/******************************************************************************* + * util/FontSizeHandler.h * + * * + * Copyright (C) 2025, Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef _FONTSIZEHANDLER_H +#define _FONTSIZEHANDLER_H + +#include + +class QWidget; +class QAbstractItemView; +class FontSizeHandlerObject; + +// Class to handle font size and message font size setting +class FontSizeHandlerBase +{ + friend class FontSizeHandlerObject; + +public: + virtual ~FontSizeHandlerBase(); + + int getFontSize(); + + void registerFontSize(QWidget *widget, std::function callback = nullptr); + void registerFontSize(QAbstractItemView *view, float iconHeightFactor = 0.0f, std::function callback = nullptr); + + void updateFontSize(QWidget *widget, std::function callback = nullptr, bool force = false); + void updateFontSize(QAbstractItemView *view, float iconHeightFactor, std::function callback, bool force = false); + +protected: + enum Type { + FONT_SIZE, + MESSAGE_FONT_SIZE + }; + + FontSizeHandlerBase(Type type); + +private: + Type mType; + FontSizeHandlerObject *mObject; +}; + +// Class to handle font size setting +class FontSizeHandler : public FontSizeHandlerBase +{ +public: + FontSizeHandler() : FontSizeHandlerBase(FONT_SIZE) {} +}; + +// Class to handle message font size setting +class MessageFontSizeHandler : public FontSizeHandlerBase +{ +public: + MessageFontSizeHandler() : FontSizeHandlerBase(MESSAGE_FONT_SIZE) {} +}; + +#endif // FONTSIZEHANDLER diff --git a/retroshare-gui/src/util/RichTextEdit.cpp b/retroshare-gui/src/util/RichTextEdit.cpp index 9d4596a82..020b13db9 100644 --- a/retroshare-gui/src/util/RichTextEdit.cpp +++ b/retroshare-gui/src/util/RichTextEdit.cpp @@ -167,7 +167,7 @@ RichTextEdit::RichTextEdit(QWidget *parent) : QWidget(parent) { QFontDatabase db; foreach(int size, db.standardSizes()) - f_fontsize->addItem(QString::number(size)); + f_fontsize->addItem(QString::number(size), size); connect(f_fontsize, SIGNAL(activated(QString)), this, SLOT(textSize(QString))); @@ -195,6 +195,9 @@ RichTextEdit::RichTextEdit(QWidget *parent) : QWidget(parent) { // check message length connect(f_textedit, SIGNAL(textChanged()), this, SLOT(checkLength())); + mMessageFontSizeHandler.registerFontSize(f_textedit, [this] (QWidget*, int fontSize) { + f_fontsize->setCurrentIndex(f_fontsize->findData(fontSize)); + }); } diff --git a/retroshare-gui/src/util/RichTextEdit.h b/retroshare-gui/src/util/RichTextEdit.h index aae9d20ab..6e4869838 100644 --- a/retroshare-gui/src/util/RichTextEdit.h +++ b/retroshare-gui/src/util/RichTextEdit.h @@ -23,6 +23,7 @@ #include #include "ui_RichTextEdit.h" +#include "util/FontSizeHandler.h" /** * @Brief A simple rich-text editor @@ -93,6 +94,9 @@ signals: ParagraphMonospace }; QPointer m_lastBlockList; + +private: + MessageFontSizeHandler mMessageFontSizeHandler; }; #endif diff --git a/retroshare-gui/src/util/RichTextEdit.ui b/retroshare-gui/src/util/RichTextEdit.ui index 63e624b5e..5bb57a792 100644 --- a/retroshare-gui/src/util/RichTextEdit.ui +++ b/retroshare-gui/src/util/RichTextEdit.ui @@ -6,7 +6,7 @@ 0 0 - 703 + 784 312 @@ -566,7 +566,6 @@ MS Sans Serif - 9 @@ -590,16 +589,16 @@ - - MimeTextEdit - QTextEdit -
gui/common/MimeTextEdit.h
-
RSComboBox QComboBox
gui/common/RSComboBox.h
+ + MimeTextEdit + QTextEdit +
gui/common/MimeTextEdit.h
+
f_textedit @@ -608,7 +607,6 @@ f_menu - diff --git a/retroshare-service/data/retroshare-service.desktop b/retroshare-service/data/retroshare-service.desktop index 5d077597b..fc8135e05 100644 --- a/retroshare-service/data/retroshare-service.desktop +++ b/retroshare-service/data/retroshare-service.desktop @@ -7,4 +7,4 @@ Exec=retroshare-service %U Icon=retroshare-service Terminal=false Type=Application -Categories=Application;Network; +Categories=Network; diff --git a/retroshare.pri b/retroshare.pri index 7858f67f6..2e8bb729a 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -132,7 +132,7 @@ use_dht_stunner_ext_ip:CONFIG -= no_use_dht_stunner_ext_ip # To select your MacOsX version append the following assignation to qmake # command line "CONFIG+=rs_macos10.11" where 10.11 depends your version -macx:CONFIG *= rs_macos10.11 +macx:CONFIG *= rs_macos11.1 rs_macos10.8:CONFIG -= rs_macos10.11 rs_macos10.9:CONFIG -= rs_macos10.11 rs_macos10.10:CONFIG -= rs_macos10.11 @@ -182,6 +182,12 @@ rs_deep_files_index_taglib:CONFIG -= no_rs_deep_files_index_taglib CONFIG *= no_rs_use_native_dialogs rs_use_native_dialogs:CONFIG -= no_rs_use_native_dialogs +# By default, use RNP lib for RFC4880 PGP management. If not, compilation will +# default to openpgp-sdk, which is old and unmaintained, so probably not very secure. +CONFIG *= rs_rnplib +rs_no_rnplib:CONFIG -= rs_rnplib +rs_no_rnplib:CONFIG += rs_openpgpsdk + # To disable broadcast discovery append the following assignation to qmake # command line "CONFIG+=no_rs_broadcast_discovery" CONFIG *= rs_broadcast_discovery @@ -280,7 +286,7 @@ isEmpty(RS_THREAD_LIB):RS_THREAD_LIB = pthread # # V07_NON_BACKWARD_COMPATIBLE_CHANGE_002: # -# What: Use RSA+SHA256 instead of RSA+SHA1 for PGP certificate signatures +# What: Use RSA+SHA256 instead of RSA+SHA1 for SSL certificates # # Why: Sha1 is likely to be prone to primary collisions anytime soon, so it is urgent to turn to a more secure solution. # @@ -290,16 +296,38 @@ isEmpty(RS_THREAD_LIB):RS_THREAD_LIB = pthread # # What: Do not hash PGP certificate twice when signing # -# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing. +# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing. # -# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017. +# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017. # # V07_NON_BACKWARD_COMPATIBLE_CHANGE_004: # # What: Do not probe that GXS tunnels accept fast items. Just assume they do. +# # Why: Avoids sending probe packets +# # BackwardCompat: old RS before Mai 2019 will not be able to distant chat. # +# V07_NON_BACKWARD_COMPATIBLE_CHANGE_005: +# +# What: Stop accepting certificates signed with sha1 algorithm +# +# Why: Sha1 has been declared insecure and shouldn't be used anymore. +# +# BackwardCompat: Retroshare profiles generated before Nov.2024 with openpgp-sdk may still use sha1 +# +########################################################################################################################################################### + +########################################################################################################################################################### +# +# V06_EXPERIMENTAL_CHANGE_001: +# +# What: removes issuer fingerprint from signature subpackets +# Why: This type of subpacket is not part of RFC4880 and not recognised by OpenPGP-SDK +# BackwardCompat: old RS before Sept.2024 will not be able to exchange keys +# Note: Since signature subpacket 33 is part of the hashed section of the signature, this also invalidates the signature. +# Depending on the implementation, certificates with self-signature that miss this subpacket may not be accepted. +# ########################################################################################################################################################### @@ -313,6 +341,7 @@ rs_v07_changes { DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 + DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_005 DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED } @@ -823,6 +852,9 @@ macx-* { QMAKE_LIBDIR += "/usr/local/opt/openssl/lib" QMAKE_LIBDIR += "/usr/local/opt/sqlcipher/lib" QMAKE_LIBDIR += "/usr/local/opt/miniupnpc/lib" + INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2" + INCLUDEPATH += "/usr/local/opt/libxslt/include" + QMAKE_LIBDIR += "/usr/local/opt/libxslt/lib" } # If not yet defined attempt UPnP library autodetection should works at least @@ -849,6 +881,19 @@ isEmpty(RS_UPNP_LIB) { } } +rs_openpgpsdk { + SUBDIRS += openpgpsdk + openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro + libretroshare.depends += openpgpsdk + message("Using OpenPGP-SDK for PGP") +} + +rs_rnplib { + DEFINES += USE_RNP_LIB + message("Using RNP lib for PGP") +} + + equals(RS_UPNP_LIB, none):RS_UPNP_LIB= equals(RS_UPNP_LIB, miniupnpc):DEFINES*=RS_USE_LIBMINIUPNPC contains(RS_UPNP_LIB, upnp):DEFINES*=RS_USE_LIBUPNP diff --git a/supportlibs/cmark b/supportlibs/cmark index b9c7a496b..3460cd809 160000 --- a/supportlibs/cmark +++ b/supportlibs/cmark @@ -1 +1 @@ -Subproject commit b9c7a496ba7dd9c3495bae2ff2855899e47b245d +Subproject commit 3460cd809b6dd311b58e92733ece2fc956224fd2 diff --git a/supportlibs/librnp b/supportlibs/librnp new file mode 160000 index 000000000..ec7811726 --- /dev/null +++ b/supportlibs/librnp @@ -0,0 +1 @@ +Subproject commit ec78117269461b2cdce15a085033a8c6bff6d7e3 diff --git a/supportlibs/libsam3 b/supportlibs/libsam3 index ea52a3251..f90555ba4 160000 --- a/supportlibs/libsam3 +++ b/supportlibs/libsam3 @@ -1 +1 @@ -Subproject commit ea52a3251d60906d67f9a1031a6ed7642753f94f +Subproject commit f90555ba4d6f9fadb6f0fbb1e2253e13557aad34 diff --git a/supportlibs/rapidjson b/supportlibs/rapidjson index f54b0e47a..24b5e7a8b 160000 --- a/supportlibs/rapidjson +++ b/supportlibs/rapidjson @@ -1 +1 @@ -Subproject commit f54b0e47a08782a6131cc3d60f94d038fa6e0a51 +Subproject commit 24b5e7a8b27f42fa16b96fc70aade9106cf7102f diff --git a/supportlibs/restbed b/supportlibs/restbed index c27c6726d..6001a3228 160000 --- a/supportlibs/restbed +++ b/supportlibs/restbed @@ -1 +1 @@ -Subproject commit c27c6726d28c42e2e1b7537ba63eeb23e944789d +Subproject commit 6001a322809b5005b8bcccdf593fdda6f0173691