Compare commits

..

No commits in common. "master" and "v0.6.7a" have entirely different histories.

202 changed files with 68958 additions and 59063 deletions

2
.gitignore vendored
View File

@ -21,7 +21,7 @@ Thumbs.db
!supportlibs/libsam3/Makefile !supportlibs/libsam3/Makefile
# QtCreator cruft # QtCreator cruft
*CMakeLists.txt.user* *CMakeLists.txt.user
# Build artifacts # Build artifacts
/jsonapi-generator/src/jsonapi-generator /jsonapi-generator/src/jsonapi-generator

View File

@ -1,7 +1,7 @@
image: docker:latest image: docker:stable
services: services:
- docker:dind - docker:stable-dind
stages: stages:
- build - build
@ -18,7 +18,6 @@ variables:
build-ubuntu-test-image: build-ubuntu-test-image:
stage: build stage: build
script: script:
- docker --version
- > - >
docker login "$CI_REGISTRY" docker login "$CI_REGISTRY"
--username "$CI_REGISTRY_USER" --username "$CI_REGISTRY_USER"
@ -36,7 +35,6 @@ build-ubuntu-test-image:
test-ubuntu: test-ubuntu:
stage: test stage: test
script: script:
- docker --version
- > - >
docker login "$CI_REGISTRY" docker login "$CI_REGISTRY"
--username "$CI_REGISTRY_USER" --username "$CI_REGISTRY_USER"

3
.gitmodules vendored
View File

@ -36,6 +36,3 @@
[submodule "retroshare-webui"] [submodule "retroshare-webui"]
path = retroshare-webui path = retroshare-webui
url = https://github.com/RetroShare/RSNewWebUI.git url = https://github.com/RetroShare/RSNewWebUI.git
[submodule "supportlibs/librnp"]
path = supportlibs/librnp
url = https://github.com/rnpgp/rnp.git

View File

@ -25,6 +25,9 @@ CONFIG += c++14
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += openpgpsdk
openpgpsdk.file = openpgpsdk/src/openpgpsdk.pro
rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) { rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) {
SUBDIRS += jsonapi-generator SUBDIRS += jsonapi-generator
jsonapi-generator.file = jsonapi-generator/src/jsonapi-generator.pro jsonapi-generator.file = jsonapi-generator/src/jsonapi-generator.pro
@ -33,7 +36,7 @@ rs_jsonapi:isEmpty(JSONAPI_GENERATOR_EXE) {
SUBDIRS += libbitdht SUBDIRS += libbitdht
libbitdht.file = libbitdht/src/libbitdht.pro libbitdht.file = libbitdht/src/libbitdht.pro
libretroshare.depends += libbitdht libretroshare.depends += openpgpsdk libbitdht
SUBDIRS += libretroshare SUBDIRS += libretroshare
libretroshare.file = libretroshare/src/libretroshare.pro libretroshare.file = libretroshare/src/libretroshare.pro

View File

@ -40,23 +40,18 @@ RUN git clone --depth 1 https://github.com/aetilius/pHash.git && \
rm -rf pHash-build pHash rm -rf pHash-build pHash
ARG FRESHCLONE=0 ARG FRESHCLONE=0
ARG REPO_URL=https://github.com/RetroShare/RetroShare.git ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
ARG REPO_BRANCH=master ARG REPO_BRANCH=master
ARG REPO_DEPTH="--depth 2000" ARG REPO_DEPTH="--depth 2000"
RUN git clone $REPO_DEPTH $REPO_URL -b $REPO_BRANCH && \ RUN git clone $REPO_DEPTH $REPO_URL -b $REPO_BRANCH && cd RetroShare && \
cd RetroShare && \
git fetch --tags && \ git fetch --tags && \
git submodule update --init \ git submodule update --init --remote --force \
libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ \ libbitdht/ libretroshare/ openpgpsdk/ && \
supportlibs/restbed/ && \ cd ..
cd supportlibs/restbed/ && \
git submodule update --init \
dependency/asio/ dependency/kashmir/ && \
cd ../../../
RUN \ RUN \
mkdir RetroShare-build && cd RetroShare-build && \ mkdir RetroShare-build && cd RetroShare-build && \
cmake -B. -S../RetroShare/retroshare-service \ cmake -B. -S../RetroShare/retroshare-service \
-DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON -DRS_WEBUI=ON && \ -DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON && \
make -j$(nproc) && make install && \ make -j$(nproc) && make install && \
cd .. && rm -rf RetroShare-build cd .. && rm -rf RetroShare-build

View File

@ -2,19 +2,19 @@ FROM registry.gitlab.com/retroshare/retroshare:base
RUN apt-get update -y && apt-get upgrade -y RUN apt-get update -y && apt-get upgrade -y
ARG REPO_URL=https://github.com/RetroShare/RetroShare.git ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
ARG REPO_BRANCH=master ARG REPO_BRANCH=master
RUN \ RUN \
cd RetroShare && git remote add testing $REPO_URL && \ cd RetroShare && git remote add testing $REPO_URL && \
git fetch --tags testing $REPO_BRANCH && \ git fetch --tags testing $REPO_BRANCH && \
git reset --hard testing/$REPO_BRANCH && \ git reset --hard testing/$REPO_BRANCH && \
git submodule update --init \ git submodule update --init --remote --force \
libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ && \ libbitdht/ libretroshare/ openpgpsdk/ && \
git --no-pager log --max-count 1 git --no-pager log --max-count 1
RUN \ RUN \
mkdir RetroShare-build && cd RetroShare-build && \ mkdir RetroShare-build && cd RetroShare-build && \
cmake -B. -S../RetroShare/retroshare-service \ cmake -B. -S../RetroShare/retroshare-service \
-DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON -DRS_WEBUI=ON \ -DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON \
-DRS_WARN_DEPRECATED=OFF -DRS_WARN_LESS=ON && \ -DRS_WARN_DEPRECATED=OFF -DRS_WARN_LESS=ON && \
make -j$(nproc) && make install && \ make -j$(nproc) && make install && \
cd .. && rm -rf RetroShare-build cd .. && rm -rf RetroShare-build

@ -1 +1 @@
Subproject commit 0a3997cc1355b2c848161dca015b7e2df039707b Subproject commit 353596b0ee5ea76611eb663b90bf3ab1c9f34ad7

View File

@ -30,42 +30,20 @@ In GitHub Desktop -> Clone Repository -> URL
Add Repository URL: https://github.com/RetroShare/RetroShare.git and Clone Add Repository URL: https://github.com/RetroShare/RetroShare.git and Clone
## ***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.
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
To install from App Store:
Select [x] menu - > "App Store…".
Search for Xcode. Download and install.
Once Xcode has installed, you must drag the XCode icon into your Applications folder. After you have done this, open Xcode from the Applications folder by double-clicking on the icon and then follow the remaining instructions below.
Install XCode command line developer tools:
$xcode-select --install
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*** ## ***Choose if you use MacPort or HomeBrew***
### MacPort Installation ### MacPort Installation
Install MacPort following this guide: [MacPort](http://guide.macports.org/#installing.xcode) Install MacPort and XCode following this guide: [MacPort and XCode](http://guide.macports.org/#installing.xcode)
Start XCode to get it updated and to able C compiler to create executables.
#### Install libraries #### Install libraries
$ sudo port -v selfupdate $ sudo port -v selfupdate
$ sudo port install openssl $ sudo port install openssl
$ sudo port install miniupnpc $ sudo port install miniupnpc
$ sudo port install libmicrohttpd
For VOIP Plugin: For VOIP Plugin:
@ -73,29 +51,26 @@ For VOIP Plugin:
$ sudo port install opencv $ sudo port install opencv
$ sudo port install ffmpeg $ sudo port install ffmpeg
Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs)
### HOMEBREW Installation ### HOMEBREW Installation
Install HomeBrew following this guide: [HomeBrew](http://brew.sh/) Install HomeBrew following this guide: [HomeBrew](http://brew.sh/)
Install XCode command line developer tools:
$xcode-select --install
Start XCode to get it updated and to able C compiler to create executables.
#### Install libraries #### Install libraries
$ brew install openssl $ brew install openssl
$ brew install miniupnpc $ brew install miniupnpc
$ brew install libmicrohttpd
$ brew install rapidjson $ brew install rapidjson
$ brew install sqlcipher $ 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
If you have error in linking, run this: If you have error in linking, run this:
$sudo chown -R $(whoami) /usr/local/lib/pkgconfig $sudo chown -R $(whoami) /usr/local/lib/pkgconfig
@ -110,7 +85,8 @@ For VOIP Plugin:
For FeedReader Plugin: For FeedReader Plugin:
$ brew install libxslt $ brew install libxslt
$ brew install libxml2
Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs)
## Last Settings ## Last Settings
@ -128,8 +104,11 @@ In QtCreator Projects -> Build -> Build Settings -> Build Steps -> Add Additiona
## Set your Mac OS SDK version ## Set your Mac OS SDK version
Edit RetroShare.pro
Edit retroshare.pri and set your installed sdk version example for 11.1 -> rs_macos11.1 (line 135:) CONFIG += c++14 rs_macos11.1
and then retroshare.pri
macx:CONFIG *= rs_macos11.1 macx:CONFIG *= rs_macos11.1
rs_macos10.8:CONFIG -= rs_macos11.1 rs_macos10.8:CONFIG -= rs_macos11.1
@ -143,7 +122,7 @@ Edit retroshare.pri and set your installed sdk version example for 11.1 -> rs_ma
## Link Include & Libraries ## Link Include & Libraries
When required edit your retroshare.pri macx-* section, check if the Include and Lib path are correct (macx-* section) Edit your retroshare.pri and add to macx-* section
INCLUDEPATH += "/usr/local/opt/openssl/include" INCLUDEPATH += "/usr/local/opt/openssl/include"
QMAKE_LIBDIR += "/usr/local/opt/openssl/lib" QMAKE_LIBDIR += "/usr/local/opt/openssl/lib"
@ -152,21 +131,13 @@ When required edit your retroshare.pri macx-* section, check if the Include and
alternative via Terminal alternative via Terminal
$ qmake $ qmake INCLUDEPATH+="/usr/local/opt/openssl/include" 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/openssl/include" \
QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \
QMAKE_LIBDIR+="/usr/local/opt/sqlcipher/lib" \
QMAKE_LIBDIR+="/usr/local/opt/miniupnpc/lib" \
CONFIG+=rs_autologin \
CONFIG+=rs_use_native_dialogs \
CONFIG+=release \
..
For FeedReader Plugin: For FeedReader Plugin:
INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2" INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2"
With plugins: For building RetroShare with plugins:
$ qmake \ $ qmake \
INCLUDEPATH+="/usr/local/opt/openssl/include" QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \ INCLUDEPATH+="/usr/local/opt/openssl/include" QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \
@ -188,30 +159,13 @@ With plugins:
You can now compile RetroShare into Qt Creator or with Terminal You can now compile RetroShare into Qt Creator or with Terminal
$ cd /path/to/retroshare cd retroshare
$ qmake .. qmake; make
$ make
You can change Target and SDK in *./retroshare.pri:82* changing value of QMAKE_MACOSX_DEPLOYMENT_TARGET and QMAKE_MAC_SDK You can change Target and SDK in *./retroshare.pri:82* changing value of QMAKE_MACOSX_DEPLOYMENT_TARGET and QMAKE_MAC_SDK
You can find the compiled application at *./retroshare/retroshare-gui/src/retroshare.app* You can find the compiled application at *./retroshare/retroshare-gui/src/retroshare.app*
## Issues
If you have issues with openssl (Undefined symbols for architecture x86_64) try to add to *~/.profile* file this or via Terminal
export PATH="/usr/local/opt/openssl/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I/usr/local/opt/openssl/include"
export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig"
For Qt Creator -> QtCreator Projects -> Build -> Build Settings -> Build Steps -> Add Additional arguments:
LDFLAGS="-L/usr/local/opt/openssl/lib"
CPPFLAGS="-I/usr/local/opt/openssl/include"
## Copy Plugins ## Copy Plugins
$ cp \ $ cp \
@ -219,13 +173,3 @@ For Qt Creator -> QtCreator Projects -> Build -> Build Settings -> Build Steps -
./plugins/VOIP/lib/libVOIP.dylib \ ./plugins/VOIP/lib/libVOIP.dylib \
./plugins/RetroChess/lib/libRetroChess.dylib \ ./plugins/RetroChess/lib/libRetroChess.dylib \
./retroshare-gui/src/RetroShare.app/Contents/Resources/ ./retroshare-gui/src/RetroShare.app/Contents/Resources/
### Compile Retroshare-Service & Webui with CMake
before you can compile overwrite the file "asio/include/asio/detail/config.hpp" here is a fix for macos [
asio fix](https://github.com/chriskohlhoff/asio/commit/68df16d560c68944809bb2947360fe8035e9ae0a)
$ cd retroshare-service
$ mkdir build-dir
$ cd build-dir
$ cmake -DRS_WEBUI=ON -DCMAKE_BUILD_TYPE=Release ..
$ make

View File

@ -1,51 +0,0 @@
#!/bin/sh
APP="RetroShare"
RSVERSION="0.6.7a"
QTVERSION="Qt-5.15.11"
# Install the 7z to create dmg archives.
#brew list p7zip || brew install p7zip
# Package your app
echo "Packaging retroshare..."
#cd ${project_dir}/build/macOS/clang/x86_64/release/
cd retroshare-gui/src/
# Remove build directories that you don't want to deploy
rm -rf moc
rm -rf obj
rm -rf qrc
# This sets the CFBundleVersion & CFBundleShortVersionString string
/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
echo "Creating dmg archive..."
macdeployqt retroshare.app -dmg
DATE=`date +"%m-%d-%Y"`
MACVERSION=`sw_vers -productVersion`
#RSVERSION=`git describe --abbrev=0 --tags`
GITHEAD=`git rev-parse --short HEAD`
mv $APP.dmg "$APP-$RSVERSION-$GITHEAD-$DATE-MacOS-$MACVERSION-$QTVERSION.dmg"
# You can use the appdmg command line app to create your dmg file if
# you want to use a custom background and icon arrangement. I'm still
# working on this for my apps, myself. If you want to do this, you'll
# remove the -dmg option above.
# appdmg json-path YourApp_${TRAVIS_TAG}.dmg
# Copy other project files
cp "../../libbitdht/src/bitdht/bdboot.txt" "retroshare.app/Contents/Resources/"
cp "../../plugins/FeedReader/lib/libFeedReader.dylib" "retroshare.app/Contents/Resources/"
cp -R "sounds" "retroshare.app/Contents/Resources/sounds"
# cp "${project_dir}/README.md" "README.md"
# cp "${project_dir}/LICENSE" "LICENSE"
# cp "${project_dir}/Qt License" "Qt License"

View File

@ -18,8 +18,6 @@ if errorlevel 1 goto error_env
if not "%ParamNoupdate%"=="1" ( if not "%ParamNoupdate%"=="1" (
:: Install needed things :: 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" %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 :: Webui
if "%ParamWebui%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-doxygen" if "%ParamWebui%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-doxygen"

View File

@ -105,7 +105,6 @@ copy "%RsBuildPath%\retroshare-nogui\src\%RsBuildConfig%\retroshare*-nogui.exe"
copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite%
copy "%RsBuildPath%\supportlibs\cmark\build\src\libcmark.dll" "%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%\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" ( if exist "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" (
copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite%
) )

View File

@ -16,7 +16,7 @@ if "%~1"=="clean" (
goto exit goto exit
) )
set MSYS2Version=20241208 set MSYS2Version=20231026
set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe 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 MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install%

View File

@ -13,18 +13,12 @@ LIBMICROHTTPD_VERSION=0.9.75
FFMPEG_VERSION=4.4 FFMPEG_VERSION=4.4
RAPIDJSON_VERSION=1.1.0 RAPIDJSON_VERSION=1.1.0
XAPIAN_VERSION=1.4.19 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 DOWNLOAD_PATH?=download
BUILD_PATH=build BUILD_PATH=build
LIBS_PATH?=libs LIBS_PATH?=libs
all: dirs zlib bzip2 miniupnpc openssl speex speexdsp libxml2 libxslt curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian jsonc botan copylibs all: dirs zlib bzip2 miniupnpc openssl speex speexdsp libxml2 libxslt curl sqlcipher libmicrohttpd ffmpeg rapidjson xapian copylibs
#rnp
download: \ download: \
$(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz \ $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz \
@ -369,57 +363,6 @@ $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION): $(DOWNLOAD_PATH)/xapian-core-$(XAPI
rm -r -f xapian-core-$(XAPIAN_VERSION) rm -r -f xapian-core-$(XAPIAN_VERSION)
mv $(BUILD_PATH)/xapian-core-$(XAPIAN_VERSION).tmp $(BUILD_PATH)/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: copylibs:
rm -r -f $(LIBS_PATH) ; \ rm -r -f $(LIBS_PATH) ; \
mkdir -p $(LIBS_PATH) ; \ mkdir -p $(LIBS_PATH) ; \

View File

@ -96,7 +96,6 @@ copy nul "%RsDeployPath%\portable" %Quite%
echo copy binaries echo copy binaries
copy "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare*.exe" "%RsDeployPath%" %Quite% 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%\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" ( if "%ParamService%"=="1" (
copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite%

View File

@ -16,13 +16,13 @@ if "%~1"=="clean" (
goto exit goto exit
) )
set MSYS2Version=20241208 set MSYS2Version=20231026
set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe 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 MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install%
set MSYS2UnpackPath=%EnvMSYS2Path%\msys64 set MSYS2UnpackPath=%EnvMSYS2Path%\msys64
set CMakeInstall=cmake-3.31.3-windows-i386.zip set CMakeInstall=cmake-3.19.0-win32-x86.zip
set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall%
if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" ( if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" (
if "%~1"=="reinstall" ( if "%~1"=="reinstall" (

View File

@ -19,9 +19,9 @@ set MinGitInstallPath=%EnvToolsPath%\MinGit
set DoxygenInstall=doxygen-1.9.6.windows.x64.bin.zip 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 DoxygenUrl=https://github.com/doxygen/doxygen/releases/download/Release_1_9_6/%DoxygenInstall%
set DoxygenInstallPath=%EnvToolsPath%\doxygen set DoxygenInstallPath=%EnvToolsPath%\doxygen
set CMakeVersion=cmake-3.31.3-windows-i386 set CMakeVersion=cmake-3.19.0-win32-x86
set CMakeInstall=%CMakeVersion%.zip set CMakeInstall=%CMakeVersion%.zip
set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.31.3/%CMakeInstall% set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall%
set CMakeInstallPath=%EnvToolsPath%\cmake set CMakeInstallPath=%EnvToolsPath%\cmake
set TorProjectUrl=https://www.torproject.org set TorProjectUrl=https://www.torproject.org
set TorDownloadIndexUrl=%TorProjectUrl%/download/tor set TorDownloadIndexUrl=%TorProjectUrl%/download/tor

View File

@ -247,7 +247,6 @@ Section $(Section_Main) Section_Main
; External binaries ; External binaries
File "${EXTERNAL_LIB_DIR}\bin\miniupnpc.dll" File "${EXTERNAL_LIB_DIR}\bin\miniupnpc.dll"
File "${RELEASEDIR}\supportlibs\librnp\Build\src\lib\librnp.dll"
!if ${ARCHITECTURE} == "x86" !if ${ARCHITECTURE} == "x86"
File "${EXTERNAL_LIB_DIR}\bin\libcrypto-1_1.dll" File "${EXTERNAL_LIB_DIR}\bin\libcrypto-1_1.dll"
File "${EXTERNAL_LIB_DIR}\bin\libssl-1_1.dll" File "${EXTERNAL_LIB_DIR}\bin\libssl-1_1.dll"

View File

@ -1,20 +0,0 @@
#!/bin/bash
function git_del_tag()
{
mTag=$1
for mRemote in $(git remote); do
echo "Attempting tag $mTag removal from remote $mRemote"
GIT_TERMINAL_PROMPT=0 git push $mRemote :$mTag || true
done
git tag --delete $mTag
}
for mModule in . build_scripts/OBS/ libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ ; do
pushd $mModule
git_del_tag v0.6.7a
git tag --list | grep untagged | while read mTag; do git_del_tag $mTag ; done
popd
done

View File

@ -7,5 +7,5 @@ Exec=/usr/bin/retroshare %U
Icon=/usr/share/pixmaps/retroshare.xpm Icon=/usr/share/pixmaps/retroshare.xpm
Terminal=false Terminal=false
Type=Application Type=Application
Categories=Application;Network;Email;InstantMessaging;Chat;Feed;FileTransfer;P2P Categories=Application;Network;P2P;Feed;Chat;InstantMessaging
MimeType=x-scheme-handler/retroshare; MimeType=x-scheme-handler/retroshare;

@ -1 +1 @@
Subproject commit 2a4df811f6bfe1904bc3956f285aa0fc891f9fd4 Subproject commit bfa91bdef24f2339f1db053d155a6ef169027a95

@ -1 +1 @@
Subproject commit df542663d8bd698a8b5541fc6db07da6c59f1c3a Subproject commit b41667912751a453e8e5d4733215a0609277a26f

View File

@ -129,8 +129,6 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n
settingsChanged(); settingsChanged();
feedTreeItemActivated(NULL); feedTreeItemActivated(NULL);
mFontSizeHandler.registerFontSize(ui->feedTreeWidget);
} }
FeedReaderDialog::~FeedReaderDialog() FeedReaderDialog::~FeedReaderDialog()

View File

@ -23,7 +23,6 @@
#include <retroshare-gui/mainpage.h> #include <retroshare-gui/mainpage.h>
#include "interface/rsFeedReader.h" #include "interface/rsFeedReader.h"
#include "util/FontSizeHandler.h"
namespace Ui { namespace Ui {
class FeedReaderDialog; class FeedReaderDialog;
@ -99,8 +98,6 @@ private:
RsFeedReader *mFeedReader; RsFeedReader *mFeedReader;
FeedReaderNotify *mNotify; FeedReaderNotify *mNotify;
FontSizeHandler mFontSizeHandler;
/** Qt Designer generated object */ /** Qt Designer generated object */
Ui::FeedReaderDialog *ui; Ui::FeedReaderDialog *ui;
}; };

View File

@ -57,10 +57,10 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QFrame" name="toolBarFrame"> <widget class="QFrame" name="toolBarFrame">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin"> <property name="leftMargin">

View File

@ -154,8 +154,6 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader *
ui->msgTreeWidget->installEventFilter(this); ui->msgTreeWidget->installEventFilter(this);
setFeedId(feedId); setFeedId(feedId);
mFontSizeHandler.registerFontSize(ui->msgTreeWidget);
} }
FeedReaderMessageWidget::~FeedReaderMessageWidget() FeedReaderMessageWidget::~FeedReaderMessageWidget()

View File

@ -24,7 +24,6 @@
#include <QWidget> #include <QWidget>
#include "interface/rsFeedReader.h" #include "interface/rsFeedReader.h"
#include "util/FontSizeHandler.h"
namespace Ui { namespace Ui {
class FeedReaderMessageWidget; class FeedReaderMessageWidget;
@ -108,8 +107,6 @@ private:
RsFeedReader *mFeedReader; RsFeedReader *mFeedReader;
FeedReaderNotify *mNotify; FeedReaderNotify *mNotify;
FontSizeHandler mFontSizeHandler;
Ui::FeedReaderMessageWidget *ui; Ui::FeedReaderMessageWidget *ui;
}; };

View File

@ -848,22 +848,6 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK; RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
time_t minimumPubDate = 0;
if (feed.lastUpdate == 0) {
// Get all items on first scan
} else {
// Get storage time
uint32_t storageTime = 0;
if (feed.flag & RS_FEED_FLAG_STANDARD_STORAGE_TIME) {
storageTime = mFeedReader->getStandardStorageTime();
} else {
storageTime = feed.storageTime;
}
if (storageTime > 0) {
minimumPubDate = time(NULL) - storageTime;
}
}
XMLWrapper xml; XMLWrapper xml;
if (xml.readXML(feed.content.c_str())) { if (xml.readXML(feed.content.c_str())) {
xmlNodePtr root = xml.getRootElement(); xmlNodePtr root = xml.getRootElement();
@ -1022,13 +1006,6 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
} }
} }
if (minimumPubDate) {
if (item->pubDate < minimumPubDate) {
// pubDate is less than storage time, don't add as new item
continue;
}
}
entries.push_back(item); entries.push_back(item);
} }
} else { } else {
@ -1120,7 +1097,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
std::string url; std::string url;
if (feed.flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE) { if (feed.flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE) {
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl;
#endif #endif
std::string content; std::string content;
CURLWrapper CURL(proxy); CURLWrapper CURL(proxy);
@ -1157,7 +1134,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
if (result != RS_FEED_ERRORSTATE_OK) { if (result != RS_FEED_ERRORSTATE_OK) {
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl;
#endif #endif
return result; return result;
} }
@ -1303,7 +1280,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
if (!src.empty()) { if (!src.empty()) {
/* download image */ /* download image */
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl;
#endif #endif
std::vector<unsigned char> data; std::vector<unsigned char> data;
CURLWrapper CURL(proxy); CURLWrapper CURL(proxy);
@ -1371,7 +1348,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
if (!html.saveHTML(msg->postedDescriptionWithoutFirstImage)) { if (!html.saveHTML(msg->postedDescriptionWithoutFirstImage)) {
errorString = html.lastError(); errorString = html.lastError();
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
std::cerr << " Error: " << errorString << std::endl; std::cerr << " Error: " << errorString << std::endl;
#endif #endif
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
@ -1380,7 +1357,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
} else { } else {
errorString = html.lastError(); errorString = html.lastError();
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
std::cerr << " Error: " << errorString << std::endl; std::cerr << " Error: " << errorString << std::endl;
#endif #endif
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR; result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
@ -1389,14 +1366,14 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
} }
} else { } else {
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl;
#endif #endif
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
} }
} else { } else {
errorString = html.lastError(); errorString = html.lastError();
#ifdef FEEDREADER_DEBUG #ifdef FEEDREADER_DEBUG
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl; std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
std::cerr << " Error: " << errorString << std::endl; std::cerr << " Error: " << errorString << std::endl;
#endif #endif
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR; result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;

View File

@ -8,11 +8,7 @@
#include "pgp/pgpkeyutil.h" #include "pgp/pgpkeyutil.h"
#include "pgp/rscertificate.h" #include "pgp/rscertificate.h"
#ifdef USE_OPENPGPSDK
#include "pgp/openpgpsdkhandler.h" #include "pgp/openpgpsdkhandler.h"
#else
#include "pgp/rnppgphandler.h"
#endif
#include "friendserver.h" #include "friendserver.h"
#include "friend_server/fsitem.h" #include "friend_server/fsitem.h"
@ -397,11 +393,7 @@ 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_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. 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); 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. // Random bias. Should be cryptographically safe.

View File

@ -2,14 +2,17 @@
README for RetroShare README for RetroShare
======================================================================================= =======================================================================================
RetroShare web site . . . . https://retroshare.cc/ RetroShare web site . . . . http://retroshare.net/index.html
Developer's blog . . . . . https://retroshareteam.wordpress.com Developer's blog . . . . . https://retroshareteam.wordpress.com
Documentation . . . . . . . https://retrosharedocs.readthedocs.io/en/latest/ Documentation . . . . . . . https://retroshare.readthedocs.io/en/latest/
Support . . . . . . . . . . http://retroshare.net/support.html
Forums . . . . . . . . . . http://retroshare.sourceforge.net/forum/
Wiki . . . . . . . . . . . https://github.com/RetroShare/documentation/wiki Wiki . . . . . . . . . . . https://github.com/RetroShare/documentation/wiki
Old developers site . . . . http://retroshare.sourceforge.net/wiki/index.php/Developers_Corner
Project site . . . . . . . https://github.com/RetroShare/RetroShare Project site . . . . . . . https://github.com/RetroShare/RetroShare
Related projects/plugins . .https://github.com/RetroShare Relted projects/plugins . . https://github.com/RetroShare
Contact: . . . . . . . . . retroshare.project@gmail.com Contact: . . . . . . . . . retroshare@lunamutt.com ,defnax@users.sourceforge.net
========================================================================================= =========================================================================================
Compiling RetroShare Compiling RetroShare
@ -19,9 +22,9 @@ Build Scripts are avaible on GIT:
https://github.com/RetroShare/RetroShare/tree/master/build_scripts https://github.com/RetroShare/RetroShare/tree/master/build_scripts
You can find here instructions howto compile RetroShare: You can find here instructions howto compile RetroShare:
https://retrosharedocs.readthedocs.io/en/latest/developer/compilation/ https://retroshare.readthedocs.io/en/latest/developer/compilation/
You can go on over to our forum or chat room when you have trouble with compiling: You can go on over to our forum or chat lobby when you have trouble with compiling:
retroshare://forum?name=Developers%20Discussions&id=8fd22bd8f99754461e7ba1ca8a727995 retroshare://forum?name=Developers%20Discussions&id=8fd22bd8f99754461e7ba1ca8a727995
retroshare://chat_room?name=Retroshare%20Devel%20%28signed%29&id=L68DB0A1E09BDA3A5 retroshare://chat_room?name=Retroshare%20Devel%20%28signed%29&id=L68DB0A1E09BDA3A5
http://retroshare.sourceforge.net/forum/

View File

@ -142,7 +142,7 @@ void AboutWidget::updateTitle()
{ {
if (tWidget == NULL) if (tWidget == NULL)
{ {
setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), RsApplication::retroshareVersion(true))); setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), Rshare::retroshareVersion(true)));
} }
else else
{ {
@ -228,7 +228,7 @@ void AWidget::initImages()
#ifdef RS_ONLYHIDDENNODE #ifdef RS_ONLYHIDDENNODE
p.drawText(QPointF(10, 50), QString("%1 : %2 (With embedded Tor)").arg(tr("Retroshare version"), Rshare::retroshareVersion(true))); p.drawText(QPointF(10, 50), QString("%1 : %2 (With embedded Tor)").arg(tr("Retroshare version"), Rshare::retroshareVersion(true)));
#else #else
p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), RsApplication::retroshareVersion(true))); p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), Rshare::retroshareVersion(true)));
#endif #endif
/* Draw Qt's version number */ /* Draw Qt's version number */
@ -936,7 +936,7 @@ void AboutWidget::on_copy_button_clicked()
{ {
QString verInfo; QString verInfo;
QString rsVerString = "RetroShare Version: "; QString rsVerString = "RetroShare Version: ";
rsVerString+=RsApplication::retroshareVersion(true); rsVerString+=Rshare::retroshareVersion(true);
verInfo+=rsVerString; verInfo+=rsVerString;
#ifdef RS_ONLYHIDDENNODE #ifdef RS_ONLYHIDDENNODE
verInfo+=" " + tr("Only Hidden Node"); verInfo+=" " + tr("Only Hidden Node");

View File

@ -143,28 +143,28 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags)
QHeaderView_setSectionResizeModeColumn(header, COLUMN_TOPIC, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(header, COLUMN_TOPIC, QHeaderView::Interactive);
privateSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); privateSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed")); privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed chat rooms"));
privateSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "1"); privateSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "1");
// privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE)); // privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE));
privateSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE); privateSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE);
ui.lobbyTreeWidget->insertTopLevelItem(0, privateSubLobbyItem); ui.lobbyTreeWidget->insertTopLevelItem(0, privateSubLobbyItem);
publicSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); publicSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed")); publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms"));
publicSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "2"); publicSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "2");
// publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC)); // publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
publicSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC); publicSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC);
ui.lobbyTreeWidget->insertTopLevelItem(1, publicSubLobbyItem); ui.lobbyTreeWidget->insertTopLevelItem(1, publicSubLobbyItem);
privateLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); privateLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
privateLobbyItem->setText(COLUMN_NAME, tr("Private")); privateLobbyItem->setText(COLUMN_NAME, tr("Private chat rooms"));
privateLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "3"); privateLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "3");
// privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE)); // privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE));
privateLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE); privateLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE);
ui.lobbyTreeWidget->insertTopLevelItem(2, privateLobbyItem); ui.lobbyTreeWidget->insertTopLevelItem(2, privateLobbyItem);
publicLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER); publicLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
publicLobbyItem->setText(COLUMN_NAME, tr("Public")); publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms"));
publicLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "4"); publicLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "4");
// publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC)); // publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
publicLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC); publicLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC);
@ -230,8 +230,6 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags)
int ltwH = misc::getFontSizeFactor("LobbyTreeWidget", 1.5).height(); int ltwH = misc::getFontSizeFactor("LobbyTreeWidget", 1.5).height();
ui.lobbyTreeWidget->setIconSize(QSize(ltwH,ltwH)); ui.lobbyTreeWidget->setIconSize(QSize(ltwH,ltwH));
mFontSizeHandler.registerFontSize(ui.lobbyTreeWidget);
} }
ChatLobbyWidget::~ChatLobbyWidget() ChatLobbyWidget::~ChatLobbyWidget()
@ -723,9 +721,9 @@ void ChatLobbyWidget::updateDisplay()
} }
} }
publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0); publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0);
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")")); publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0); privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0);
publicLobbyItem->setText(COLUMN_NAME, tr("Public")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")")); publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")"));
} }
void ChatLobbyWidget::createChatLobby() void ChatLobbyWidget::createChatLobby()

View File

@ -25,7 +25,6 @@
#include "chat/ChatLobbyUserNotify.h" #include "chat/ChatLobbyUserNotify.h"
#include "gui/gxs/GxsIdChooser.h" #include "gui/gxs/GxsIdChooser.h"
#include "util/FontSizeHandler.h"
#include <retroshare/rsmsgs.h> #include <retroshare/rsmsgs.h>
@ -147,8 +146,6 @@ private:
QAbstractButton* myInviteYesButton; QAbstractButton* myInviteYesButton;
GxsIdChooser* myInviteIdChooser; GxsIdChooser* myInviteIdChooser;
FontSizeHandler mFontSizeHandler;
/* UI - from Designer */ /* UI - from Designer */
Ui::ChatLobbyWidget ui; Ui::ChatLobbyWidget ui;
}; };

View File

@ -191,6 +191,11 @@
</item> </item>
<item> <item>
<widget class="RSTreeWidget" name="lobbyTreeWidget"> <widget class="RSTreeWidget" name="lobbyTreeWidget">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>16</width> <width>16</width>
@ -459,7 +464,7 @@
<customwidget> <customwidget>
<class>LineEditClear</class> <class>LineEditClear</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header>gui/common/LineEditClear.h</header> <header location="global">gui/common/LineEditClear.h</header>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>RSTreeWidget</class> <class>RSTreeWidget</class>

16
retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp Executable file → Normal file
View File

@ -102,7 +102,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
multi *= 1024.0; multi *= 1024.0;
} }
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_REMAINING: case COLUMN_REMAINING:
remaining = index.data().toLongLong(); remaining = index.data().toLongLong();
@ -121,7 +121,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
multi *= 1024.0; multi *= 1024.0;
} }
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_COMPLETED: case COLUMN_COMPLETED:
completed = index.data().toLongLong(); completed = index.data().toLongLong();
@ -140,7 +140,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
multi *= 1024.0; multi *= 1024.0;
} }
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_DLSPEED: case COLUMN_DLSPEED:
dlspeed = index.data().toDouble(); dlspeed = index.data().toDouble();
@ -151,7 +151,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
temp.sprintf("%.2f", dlspeed/1024.); temp.sprintf("%.2f", dlspeed/1024.);
temp += " KB/s"; temp += " KB/s";
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_PROGRESS: case COLUMN_PROGRESS:
{ {
@ -236,7 +236,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off);
pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
if (pixmapRect.isValid()){ if (pixmapRect.isValid()){
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
p.setX( p.x() + pixOffset); p.setX( p.x() + pixOffset);
painter->drawPixmap(p, pixmap); painter->drawPixmap(p, pixmap);
temp = " " + temp; temp = " " + temp;
@ -247,13 +247,13 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off);
pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
if (pixmapRect.isValid()){ if (pixmapRect.isValid()){
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
p.setX( p.x() + pixOffset); p.setX( p.x() + pixOffset);
painter->drawPixmap(p, pixmap); painter->drawPixmap(p, pixmap);
temp = " " + temp; temp = " " + temp;
pixOffset += pixmap.size().width(); pixOffset += pixmap.size().width();
} }
painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft | Qt::AlignVCenter, temp); painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft, temp);
} }
break; break;
case COLUMN_LASTDL: case COLUMN_LASTDL:
@ -279,7 +279,7 @@ QSize DLListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModel
{ {
float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString()); float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString());
int S = QFontMetricsF(option.font).height()*1.5 ; int S = QFontMetricsF(option.font).height() ;
return QSize(w,S); return QSize(w,S);
} }

View File

@ -30,7 +30,7 @@
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "retroshare-gui/RsAutoUpdatePage.h" #include "retroshare-gui/RsAutoUpdatePage.h"
#include "gui/msgs/MessageComposer.h" #include "gui/msgs/MessageComposer.h"
#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsCollection.h"
#include "gui/common/FilesDefs.h" #include "gui/common/FilesDefs.h"
#include "gui/common/RsUrlHandler.h" #include "gui/common/RsUrlHandler.h"
#include "gui/settings/rsharesettings.h" #include "gui/settings/rsharesettings.h"
@ -38,7 +38,6 @@
#include "gui/common/RSTreeWidgetItem.h" #include "gui/common/RSTreeWidgetItem.h"
#include "util/QtVersion.h" #include "util/QtVersion.h"
#include "util/qtthreadsutils.h" #include "util/qtthreadsutils.h"
#include "util/misc.h"
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
#include <retroshare/rsturtle.h> #include <retroshare/rsturtle.h>
@ -202,6 +201,10 @@ SearchDialog::SearchDialog(QWidget *parent)
ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder); 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 */ /* Set initial size the splitter */
QList<int> sizes; QList<int> sizes;
sizes << 250 << width(); // Qt calculates the right sizes sizes << 250 << width(); // Qt calculates the right sizes
@ -236,8 +239,6 @@ SearchDialog::SearchDialog(QWidget *parent)
RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this ); RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this );
}, mEventHandlerId, RsEventType::FILE_TRANSFER ); }, mEventHandlerId, RsEventType::FILE_TRANSFER );
mFontSizeHandler.registerFontSize(ui.searchSummaryWidget);
mFontSizeHandler.registerFontSize(ui.searchResultWidget, 1.4f);
} }
SearchDialog::~SearchDialog() SearchDialog::~SearchDialog()
@ -324,7 +325,7 @@ void SearchDialog::checkText(const QString& txt)
ui.searchButton->setDisabled(txt.length() < 3); ui.searchButton->setDisabled(txt.length() < 3);
ui.searchLineFrame->setProperty("valid", (txt.length() >= 3)); ui.searchLineFrame->setProperty("valid", (txt.length() >= 3));
ui.searchLineFrame->style()->unpolish(ui.searchLineFrame); ui.searchLineFrame->style()->unpolish(ui.searchLineFrame);
RsApplication::refreshStyleSheet(ui.searchLineFrame, false); Rshare::refreshStyleSheet(ui.searchLineFrame, false);
} }
void SearchDialog::initialiseFileTypeMappings() void SearchDialog::initialiseFileTypeMappings()
@ -496,23 +497,25 @@ void SearchDialog::collCreate()
int selectedCount = selectedItems.size() ; int selectedCount = selectedItems.size() ;
QTreeWidgetItem * item ; QTreeWidgetItem * item ;
RsFileTree tree; for (int i = 0; i < selectedCount; ++i) {
for (int i = 0; i < selectedCount; ++i)
{
item = selectedItems.at(i) ; item = selectedItems.at(i) ;
if (!item->text(SR_HASH_COL).isEmpty()) if (!item->text(SR_HASH_COL).isEmpty()) {
{
std::string name = item->text(SR_NAME_COL).toUtf8().constData(); std::string name = item->text(SR_NAME_COL).toUtf8().constData();
RsFileHash hash( item->text(SR_HASH_COL).toStdString() ); RsFileHash hash( item->text(SR_HASH_COL).toStdString() );
uint64_t count = item->text(SR_SIZE_COL).toULongLong(); uint64_t count = item->text(SR_SIZE_COL).toULongLong();
tree.addFile(tree.root(),name,hash,count); DirDetails details;
details.name = name;
details.hash = hash;
details.size = count;
details.type = DIR_TYPE_FILE;
dirVec.push_back(details);
} }
} }
RsCollectionDialog::openNewCollection(tree); RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this);
} }
void SearchDialog::collModif() void SearchDialog::collModif()
@ -539,8 +542,12 @@ void SearchDialog::collModif()
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
} }
void SearchDialog::collView() void SearchDialog::collView()
@ -567,8 +574,12 @@ void SearchDialog::collView()
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
}//if (qinfo.exists())
} }
void SearchDialog::collOpen() void SearchDialog::collOpen()
@ -586,35 +597,32 @@ void SearchDialog::collOpen()
if (rsFiles->FileDetails(hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL if (rsFiles->FileDetails(hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL
| RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE
| RS_FILE_HINTS_SPEC_ONLY, info)) | RS_FILE_HINTS_SPEC_ONLY, info)) {
{
/* make path for downloaded files */ /* make path for downloaded files */
std::string path; std::string path;
path = info.path; path = info.path;
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
RsCollection::RsCollectionErrorCode err;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return;
}
}
}
} }
} }
} }
QString fileName; RsCollection collection;
if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) if (collection.load(this)) {
return ; collection.downloadFiles();
}//if (collection.load(this))
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
RsCollection::RsCollectionErrorCode err;
RsCollection collection(fileName, err);
if(err == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR)
RsCollectionDialog::downloadFiles(collection);
else
QMessageBox::information(nullptr,tr("Error open RsCollection file"),RsCollection::errorString(err));
} }
void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base) void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base)
@ -1040,7 +1048,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons
child->setText(SR_SOURCES_COL, QString::number(1)); child->setText(SR_SOURCES_COL, QString::number(1));
child->setData(SR_SOURCES_COL, ROLE_SORT, 1); child->setData(SR_SOURCES_COL, ROLE_SORT, 1);
child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight );
child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_SEARCH_ID_COL, sid_hexa);
setIconAndType(child, QString::fromUtf8(dir.name.c_str())); setIconAndType(child, QString::fromUtf8(dir.name.c_str()));
@ -1065,7 +1073,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons
child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight );
child->setText(SR_SOURCES_COL, QString::number(1)); child->setText(SR_SOURCES_COL, QString::number(1));
child->setData(SR_SOURCES_COL, ROLE_SORT, 1); child->setData(SR_SOURCES_COL, ROLE_SORT, 1);
child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight );
child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_SEARCH_ID_COL, sid_hexa);
child->setText(SR_TYPE_COL, tr("Folder")); child->setText(SR_TYPE_COL, tr("Folder"));
@ -1134,7 +1142,7 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons
child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight );
child->setText(SR_SOURCES_COL, QString::number(1)); child->setText(SR_SOURCES_COL, QString::number(1));
child->setData(SR_SOURCES_COL, ROLE_SORT, 1); child->setData(SR_SOURCES_COL, ROLE_SORT, 1);
child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); child->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight );
child->setText(SR_SEARCH_ID_COL, sid_hexa); child->setText(SR_SEARCH_ID_COL, sid_hexa);
child->setText(SR_TYPE_COL, tr("Folder")); child->setText(SR_TYPE_COL, tr("Folder"));
@ -1329,8 +1337,6 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s
item->setText(SR_AGE_COL, QString::number(file.mtime)); item->setText(SR_AGE_COL, QString::number(file.mtime));
item->setData(SR_AGE_COL, ROLE_SORT, file.mtime); item->setData(SR_AGE_COL, ROLE_SORT, file.mtime);
item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight );
item->setTextAlignment( SR_AGE_COL, Qt::AlignCenter );
int friendSource = 0; int friendSource = 0;
int anonymousSource = 0; int anonymousSource = 0;
if(searchType == FRIEND_SEARCH) if(searchType == FRIEND_SEARCH)
@ -1349,7 +1355,7 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s
item->setText(SR_SOURCES_COL,modifiedResult); item->setText(SR_SOURCES_COL,modifiedResult);
item->setToolTip(SR_SOURCES_COL, tr("Obtained via ")+QString::fromStdString(rsPeers->getPeerName(file.id)) ); item->setToolTip(SR_SOURCES_COL, tr("Obtained via ")+QString::fromStdString(rsPeers->getPeerName(file.id)) );
item->setData(SR_SOURCES_COL, ROLE_SORT, fltRes); item->setData(SR_SOURCES_COL, ROLE_SORT, fltRes);
item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight | Qt::AlignVCenter ); item->setTextAlignment( SR_SOURCES_COL, Qt::AlignRight );
item->setText(SR_SEARCH_ID_COL, sid_hexa); item->setText(SR_SEARCH_ID_COL, sid_hexa);
QColor foreground; QColor foreground;

View File

@ -25,7 +25,6 @@
#include "retroshare/rsevents.h" #include "retroshare/rsevents.h"
#include "ui_SearchDialog.h" #include "ui_SearchDialog.h"
#include "retroshare-gui/mainpage.h" #include "retroshare-gui/mainpage.h"
#include "util/FontSizeHandler.h"
class AdvancedSearchDialog; class AdvancedSearchDialog;
class RSTreeWidgetItemCompareRole; class RSTreeWidgetItemCompareRole;
@ -174,8 +173,6 @@ private:
QAction *collViewAct; QAction *collViewAct;
QAction *collOpenAct; QAction *collOpenAct;
FontSizeHandler mFontSizeHandler;
/** Qt Designer generated object */ /** Qt Designer generated object */
Ui::SearchDialog ui; Ui::SearchDialog ui;

View File

@ -27,7 +27,7 @@
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "gui/ShareManager.h" #include "gui/ShareManager.h"
#include "gui/common/PeerDefs.h" #include "gui/common/PeerDefs.h"
#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsCollection.h"
#include "gui/msgs/MessageComposer.h" #include "gui/msgs/MessageComposer.h"
#include "gui/gxschannels/GxsChannelDialog.h" #include "gui/gxschannels/GxsChannelDialog.h"
#include "gui/gxsforums/GxsForumsDialog.h" #include "gui/gxsforums/GxsForumsDialog.h"
@ -652,7 +652,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName(); QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->totalFileSize(),ft->numFiles(),QString::fromStdString(ft->toRadix64())) ; RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ;
if(link.valid()) if(link.valid())
urls.push_back(link) ; urls.push_back(link) ;
@ -734,32 +734,7 @@ void SharedFilesDialog::sendLinkTo()
void SharedFilesDialog::collCreate() void SharedFilesDialog::collCreate()
{ {
QModelIndexList lst = getSelected(); QModelIndexList lst = getSelected();
model->createCollectionFile(this, lst);
std::vector <DirDetails> dirVec;
model->getDirDetailsFromSelect(lst, dirVec);
auto RemoteMode = isRemote();
FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
QString dir_name;
if(!RemoteMode)
{
if(!dirVec.empty())
{
const DirDetails& details = dirVec[0];
dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
}
}
RsFileTree tree;
for(uint32_t i=0;i<dirVec.size();++i)
tree.addFileTree(tree.root(),*RsFileTree::fromDirDetails(dirVec[i],RemoteMode,true));
RsCollectionDialog::openNewCollection(tree);
//auto ft = RsFileTree::fromDirDetails(details,remote);
} }
void SharedFilesDialog::collModif() void SharedFilesDialog::collModif()
@ -784,8 +759,12 @@ void SharedFilesDialog::collModif()
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::editExistingCollection(qinfo.absoluteFilePath()); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}
}
} }
void SharedFilesDialog::collView() void SharedFilesDialog::collView()
@ -810,8 +789,12 @@ void SharedFilesDialog::collView()
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}
}
} }
void SharedFilesDialog::collOpen() void SharedFilesDialog::collOpen()
@ -838,24 +821,20 @@ void SharedFilesDialog::collOpen()
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists()) { if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) { if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(),true); if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return;
}
} }
} }
} }
} }
QString fileName; RsCollection collection;
if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) if (collection.load(this)) {
return ; collection.downloadFiles();
}
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
RsCollection::RsCollectionErrorCode err;
RsCollection collection(fileName,err);
if(err == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR)
RsCollectionDialog::downloadFiles(collection);
} }
void LocalSharedFilesDialog::playselectedfiles() void LocalSharedFilesDialog::playselectedfiles()
@ -1166,14 +1145,12 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
collViewAct->setEnabled(bIsRsColl); collViewAct->setEnabled(bIsRsColl);
collOpenAct->setEnabled(true); collOpenAct->setEnabled(true);
QMenu collectionMenu(tr("Retroshare Collection"), this); QMenu collectionMenu(tr("Collection"), this);
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY)); collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
collectionMenu.addAction(collCreateAct); collectionMenu.addAction(collCreateAct);
if(bIsRsColl)
collectionMenu.addAction(collModifAct); collectionMenu.addAction(collModifAct);
//collectionMenu.addAction(collViewAct); collectionMenu.addAction(collViewAct);
//collectionMenu.addAction(collOpenAct); collectionMenu.addAction(collOpenAct);
switch (type) { switch (type) {
case DIR_TYPE_DIR : case DIR_TYPE_DIR :
@ -1711,16 +1688,12 @@ bool SharedFilesDialog::tree_FilterItem(const QModelIndex &index, const QString
void SharedFilesDialog::updateFontSize() void SharedFilesDialog::updateFontSize()
{ {
#if defined(Q_OS_DARWIN)
int customFontSize = Settings->valueFromGroup("File", "MinimumFontSize", 13).toInt();
#else
int customFontSize = Settings->valueFromGroup("File", "MinimumFontSize", 11).toInt(); int customFontSize = Settings->valueFromGroup("File", "MinimumFontSize", 11).toInt();
#endif
QFont newFont = ui.dirTreeView->font(); QFont newFont = ui.dirTreeView->font();
if (newFont.pointSize() != customFontSize) { if (newFont.pointSize() != customFontSize) {
newFont.setPointSize(customFontSize); newFont.setPointSize(customFontSize);
QFontMetricsF fontMetrics(newFont); QFontMetricsF fontMetrics(newFont);
int iconHeight = fontMetrics.height()*1.5; int iconHeight = fontMetrics.height();
ui.dirTreeView->setFont(newFont); ui.dirTreeView->setFont(newFont);
ui.dirTreeView->setIconSize(QSize(iconHeight, iconHeight)); ui.dirTreeView->setIconSize(QSize(iconHeight, iconHeight));
} }

View File

@ -23,10 +23,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin"> <property name="leftMargin">
@ -399,8 +399,8 @@ border-image: url(:/images/closepressed.png)
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../icons.qrc"/>
<include location="../images.qrc"/> <include location="../images.qrc"/>
<include location="../icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -24,7 +24,7 @@
#include "gui/SoundManager.h" #include "gui/SoundManager.h"
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "gui/common/FilesDefs.h" #include "gui/common/FilesDefs.h"
#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsCollection.h"
#include "gui/common/RSTreeView.h" #include "gui/common/RSTreeView.h"
#include "gui/common/RsUrlHandler.h" #include "gui/common/RsUrlHandler.h"
#include "gui/FileTransfer/DetailsDialog.h" #include "gui/FileTransfer/DetailsDialog.h"
@ -1975,7 +1975,7 @@ void TransfersDialog::pasteLink()
for(auto &it : links) for(auto &it : links)
col.merge_in(it.name(),it.size(),RsFileHash(it.hash().toStdString())) ; col.merge_in(it.name(),it.size(),RsFileHash(it.hash().toStdString())) ;
RsCollectionDialog::downloadFiles(col); col.downloadFiles();
} }
void TransfersDialog::getDLSelectedItems(std::set<RsFileHash> *ids, std::set<int> *rows) void TransfersDialog::getDLSelectedItems(std::set<RsFileHash> *ids, std::set<int> *rows)
@ -2466,17 +2466,21 @@ void TransfersDialog::collCreate()
std::set<RsFileHash>::iterator it ; std::set<RsFileHash>::iterator it ;
getDLSelectedItems(&items, NULL); getDLSelectedItems(&items, NULL);
RsFileTree tree;
for (it = items.begin(); it != items.end(); ++it) for (it = items.begin(); it != items.end(); ++it)
{ {
FileInfo info; FileInfo info;
if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue;
tree.addFile(tree.root(),info.fname,info.hash,info.size); DirDetails details;
details.name = info.fname;
details.hash = info.hash;
details.size = info.size;
details.type = DIR_TYPE_FILE;
dirVec.push_back(details);
} }
RsCollectionDialog::openNewCollection(tree); RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this);
} }
void TransfersDialog::collModif() void TransfersDialog::collModif()
@ -2500,8 +2504,12 @@ void TransfersDialog::collModif()
/* open collection */ /* open collection */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath()); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}
}
} }
} }
@ -2526,8 +2534,12 @@ void TransfersDialog::collView()
/* open collection */ /* open collection */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true); if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath(), true);
}
}
} }
} }
@ -2552,29 +2564,23 @@ void TransfersDialog::collOpen()
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) if (qinfo.exists()) {
{ if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection::RsCollectionErrorCode code; RsCollection collection;
RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),code)); if (collection.load(qinfo.absoluteFilePath())) {
collection.downloadFiles();
return; return;
} }
} }
} }
} }
}
}
QString fileName; RsCollection collection;
if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName)) if (collection.load(this)) {
return ; collection.downloadFiles();
}
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
RsCollection::RsCollectionErrorCode code;
RsCollection collection(fileName,code);
if(code == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR)
RsCollectionDialog::downloadFiles(collection);
else
QMessageBox::information(nullptr,tr("Error openning collection file"),RsCollection::errorString(code));
} }
void TransfersDialog::collAutoOpen(const QString &fileHash) void TransfersDialog::collAutoOpen(const QString &fileHash)
@ -2586,18 +2592,21 @@ void TransfersDialog::collAutoOpen(const QString &fileHash)
if (rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info)) { if (rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info)) {
/* make path for downloaded files */ /* make path for downloaded files */
if (info.downloadStatus == FT_STATE_COMPLETE) if (info.downloadStatus == FT_STATE_COMPLETE) {
{
std::string path; std::string path;
path = info.path + "/" + info.fname; path = info.path + "/" + info.fname;
/* open file with a suitable application */ /* open file with a suitable application */
QFileInfo qinfo; QFileInfo qinfo;
qinfo.setFile(QString::fromUtf8(path.c_str())); qinfo.setFile(QString::fromUtf8(path.c_str()));
RsCollection::RsCollectionErrorCode err; if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) RsCollection collection;
RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err)); if (collection.load(qinfo.absoluteFilePath(), false)) {
collection.autoDownloadFiles();
}
}
}
} }
} }
} }

12
retroshare-gui/src/gui/FileTransfer/ULListDelegate.cpp Executable file → Normal file
View File

@ -101,7 +101,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
multi *= 1024.0; multi *= 1024.0;
} }
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_UTRANSFERRED: case COLUMN_UTRANSFERRED:
transferred = index.data().toLongLong(); transferred = index.data().toLongLong();
@ -120,7 +120,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
multi *= 1024.0; multi *= 1024.0;
} }
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_ULSPEED: case COLUMN_ULSPEED:
ulspeed = index.data().toDouble(); ulspeed = index.data().toDouble();
@ -131,7 +131,7 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
temp.sprintf("%.2f", ulspeed/1024.); temp.sprintf("%.2f", ulspeed/1024.);
temp += " KB/s"; temp += " KB/s";
} }
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp); painter->drawText(option.rect, Qt::AlignRight, temp);
break; break;
case COLUMN_UPROGRESS: case COLUMN_UPROGRESS:
{ {
@ -164,10 +164,10 @@ void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off);
pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
if (pixmapRect.isValid()){ if (pixmapRect.isValid()){
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft(); QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
painter->drawPixmap(p, pixmap); painter->drawPixmap(p, pixmap);
} }
painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft | Qt::AlignVCenter, index.data().toString()); painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString());
break; break;
default: default:
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
@ -181,7 +181,7 @@ QSize ULListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModel
{ {
float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString()); float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString());
int S = QFontMetricsF(option.font).height()*1.5 ; int S = QFontMetricsF(option.font).height() ;
return QSize(w,S); return QSize(w,S);
} }

View File

@ -251,7 +251,7 @@ void GenCertDialog::initKeyList()
void GenCertDialog::mouseMoveEvent(QMouseEvent *e) void GenCertDialog::mouseMoveEvent(QMouseEvent *e)
{ {
//std::cerr << "Mouse : " << e->x() << ", " << e->y() << std::endl; std::cerr << "Mouse : " << e->x() << ", " << e->y() << std::endl;
QDialog::mouseMoveEvent(e) ; QDialog::mouseMoveEvent(e) ;
} }
@ -649,7 +649,7 @@ void GenCertDialog::genPerson()
{ {
/* complete the process */ /* complete the process */
RsInit::LoadPassword(sslPasswd); RsInit::LoadPassword(sslPasswd);
if (RsApplication::loadCertificate(sslId, false)) { if (Rshare::loadCertificate(sslId, false)) {
// Normally we should clear the cached passphrase as soon as possible. However,some other GUI components may still need it at start. // Normally we should clear the cached passphrase as soon as possible. However,some other GUI components may still need it at start.
// (csoler) This is really bad: we have to guess that 30 secs will be enough. I have no better way to do this. // (csoler) This is really bad: we have to guess that 30 secs will be enough. I have no better way to do this.

View File

@ -421,7 +421,7 @@ void GetStartedDialog::emailSupport()
sysVersion = "Linux"; sysVersion = "Linux";
#endif #endif
#endif #endif
text += QString("My RetroShare Configuration is: (%1, %2, %3)").arg(RsApplication::retroshareVersion(true) text += QString("My RetroShare Configuration is: (%1, %2, %3)").arg(Rshare::retroshareVersion(true)
, sysVersion , sysVersion
).arg(static_cast<typename std::underlying_type<RsConfigUserLvl>::type>(userLevel)) + "\n"; ).arg(static_cast<typename std::underlying_type<RsConfigUserLvl>::type>(userLevel)) + "\n";
text += "\n"; text += "\n";

View File

@ -80,7 +80,7 @@ HelpDialog::HelpDialog(QWidget *parent) :
ui->thanks->setHtml(in.readAll()); ui->thanks->setHtml(in.readAll());
} }
ui->version->setText(RsApplication::retroshareVersion(true)); ui->version->setText(Rshare::retroshareVersion(true));
/* Add version numbers of libretroshare */ /* Add version numbers of libretroshare */
std::list<RsLibraryInfo> libraries; std::list<RsLibraryInfo> libraries;

View File

@ -43,6 +43,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>Courier New</family> <family>Courier New</family>
<pointsize>10</pointsize>
<weight>75</weight> <weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
@ -87,6 +88,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize>
<weight>75</weight> <weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
@ -105,7 +107,7 @@
<string>...</string> <string>...</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="images.qrc">
<normaloff>:/icons/help_64.png</normaloff>:/icons/help_64.png</iconset> <normaloff>:/icons/help_64.png</normaloff>:/icons/help_64.png</iconset>
</property> </property>
<property name="checkable"> <property name="checkable">
@ -231,6 +233,11 @@
</item> </item>
<item row="1" column="0" colspan="5"> <item row="1" column="0" colspan="5">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Open Source cross-platform, <string>Open Source cross-platform,
private and secure decentralized communication platform. private and secure decentralized communication platform.
@ -310,6 +317,11 @@ private and secure decentralized communication platform.
</item> </item>
<item row="0" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
@ -393,6 +405,11 @@ private and secure decentralized communication platform.
</item> </item>
<item row="0" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Do you need help with Retroshare?</string> <string>Do you need help with Retroshare?</string>
</property> </property>
@ -407,8 +424,8 @@ private and secure decentralized communication platform.
</layout> </layout>
</widget> </widget>
<resources> <resources>
<include location="icons.qrc"/>
<include location="images.qrc"/> <include location="images.qrc"/>
<include location="icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,8 @@
#define IDENTITYDIALOG_H #define IDENTITYDIALOG_H
#include "gui/gxs/RsGxsUpdateBroadcastPage.h" #include "gui/gxs/RsGxsUpdateBroadcastPage.h"
#include "util/FontSizeHandler.h"
#include "retroshare/rsidentity.h" #include <retroshare/rsidentity.h>
#include "IdentityListModel.h"
#include <QTimer> #include <QTimer>
@ -36,11 +34,7 @@ class IdDialog;
} }
class UIStateHelper; class UIStateHelper;
class QStyledItemDelegate;
class QTreeWidgetItem; class QTreeWidgetItem;
class RsIdentityListModel;
class IdListSortFilterProxyModel;
class QItemSelection;
class IdDialog : public MainPage class IdDialog : public MainPage
{ {
@ -64,7 +58,6 @@ protected:
void loadIdentity(RsGxsIdGroup id_data); void loadIdentity(RsGxsIdGroup id_data);
void loadCircles(const std::list<RsGroupMetaData>& circle_metas); void loadCircles(const std::list<RsGroupMetaData>& circle_metas);
void updateIdListRequest();
//void requestCircleGroupData(const RsGxsCircleId& circle_id); //void requestCircleGroupData(const RsGxsCircleId& circle_id);
bool getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) ; bool getItemCircleId(QTreeWidgetItem *item,RsGxsCircleId& id) ;
@ -75,11 +68,11 @@ protected:
private slots: private slots:
void updateIdList(); void updateIdList();
void updateCircles(); void updateCircles();
void createExternalCircle(); void createExternalCircle();
void showEditExistingCircle(); void showEditExistingCircle();
void updateCirclesDisplay(); void updateCirclesDisplay();
void toggleAutoBanIdentities(bool b); void toggleAutoBanIdentities(bool b);
void sortColumn(int col,Qt::SortOrder so);
void acceptCircleSubscription() ; void acceptCircleSubscription() ;
void cancelCircleSubscription() ; void cancelCircleSubscription() ;
@ -93,20 +86,17 @@ private slots:
void removeIdentity(); void removeIdentity();
void editIdentity(); void editIdentity();
void chatIdentity(); void chatIdentity();
void chatIdentityItem(const QModelIndex &indx); void chatIdentityItem(QTreeWidgetItem* item);
void chatIdentity(const RsGxsId& toGxsId);
void sendMsg(); void sendMsg();
void copyRetroshareLink(); void copyRetroshareLink();
void on_closeInfoFrameButton_Invite_clicked(); void on_closeInfoFrameButton_Invite_clicked();
void updateSelection(const QItemSelection &new_sel, const QItemSelection &old_sel); void updateSelection();
void modifyReputation(); void modifyReputation();
/** Create the context popup menu and it's submenus */ /** Create the context popup menu and it's submenus */
void IdListCustomPopupMenu( QPoint point ); void IdListCustomPopupMenu( QPoint point );
void headerContextMenuRequested(QPoint);
void toggleColumnVisible();
void CircleListCustomPopupMenu(QPoint point) ; void CircleListCustomPopupMenu(QPoint point) ;
#ifdef SUSPENDED #ifdef SUSPENDED
@ -127,11 +117,6 @@ private:
void processSettings(bool load); void processSettings(bool load);
QString createUsageString(const RsIdentityUsage& u) const; QString createUsageString(const RsIdentityUsage& u) const;
void saveExpandedPathsAndSelection_idTreeView(std::set<QStringList> &expanded, std::set<QStringList> &selected);
void restoreExpandedPathsAndSelection_idTreeView(const std::set<QStringList>& expanded, const std::set<QStringList>& selelected);
void recursSaveExpandedItems_idTreeView(const QModelIndex& index, const QStringList& parent_path, std::set<QStringList>& expanded, std::set<QStringList>& selected);
void recursRestoreExpandedItems_idTreeView(const QModelIndex& index,const QStringList& parent_path,const std::set<QStringList>& expanded,const std::set<QStringList>& selected);
void requestIdData(std::list<RsGxsGroupId> &ids); void requestIdData(std::list<RsGxsGroupId> &ids);
bool fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept); bool fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item, const RsPgpId &ownPgpId, int accept);
void insertIdList(uint32_t token); void insertIdList(uint32_t token);
@ -149,32 +134,20 @@ private:
private: private:
UIStateHelper *mStateHelper; UIStateHelper *mStateHelper;
QTreeWidgetItem *contactsItem;
QTreeWidgetItem *allItem;
QTreeWidgetItem *ownItem;
QTreeWidgetItem *mExternalBelongingCircleItem; QTreeWidgetItem *mExternalBelongingCircleItem;
QTreeWidgetItem *mExternalOtherCircleItem; QTreeWidgetItem *mExternalOtherCircleItem;
QTreeWidgetItem *mMyCircleItem; QTreeWidgetItem *mMyCircleItem;
RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ; RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ;
int mLastSortColumn;
Qt::SortOrder mLastSortOrder;
void saveExpandedCircleItems(std::vector<bool> &expanded_root_items, std::set<RsGxsCircleId>& expanded_circle_items) const; void saveExpandedCircleItems(std::vector<bool> &expanded_root_items, std::set<RsGxsCircleId>& expanded_circle_items) const;
void restoreExpandedCircleItems(const std::vector<bool>& expanded_root_items,const std::set<RsGxsCircleId>& expanded_circle_items); void restoreExpandedCircleItems(const std::vector<bool>& expanded_root_items,const std::set<RsGxsCircleId>& expanded_circle_items);
void applyWhileKeepingTree(std::function<void()> predicate);
RsGxsId getSelectedIdentity() const;
std::list<RsGxsId> getSelectedIdentities() const;
RsGxsGroupId mId; RsGxsGroupId mId;
RsGxsGroupId mIdToNavigate; RsGxsGroupId mIdToNavigate;
int filter; 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<const RsEvent> event); void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
RsEventsHandlerId_t mEventHandlerId_identity; RsEventsHandlerId_t mEventHandlerId_identity;
@ -184,8 +157,6 @@ private:
bool needUpdateIdsOnNextShow; bool needUpdateIdsOnNextShow;
bool needUpdateCirclesOnNextShow; bool needUpdateCirclesOnNextShow;
FontSizeHandler mFontSizeHandler;
/* UI - Designer */ /* UI - Designer */
Ui::IdDialog *ui; Ui::IdDialog *ui;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -703,7 +703,7 @@ void IdEditDialog::updateInterface()
const QPixmap *pixmap = ui->avatarLabel->pixmap(); const QPixmap *pixmap = ui->avatarLabel->pixmap();
if (pixmap && !pixmap->isNull()) { if (pixmap && !pixmap->isNull()) {
ui->removeButton->setEnabled(true); ui->removeButton->setEnabled(true);
} else if (mEditGroup.mImage.mSize > 0) { } else if (mEditGroup.mImage.mSize != NULL) {
ui->removeButton->setEnabled(true); ui->removeButton->setEnabled(true);
} else { } else {
ui->removeButton->setEnabled(false); ui->removeButton->setEnabled(false);

View File

@ -1,968 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/msgs/RsFriendListModel.cpp *
* *
* Copyright 2019 by Cyril Soler <csoler@users.sourceforge.net> *
* *
* 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 <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <list>
#include <QApplication>
#include <QDateTime>
#include <QFontMetrics>
#include <QModelIndex>
#include <QTreeView>
#include <QPainter>
#include <QIcon>
#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<RsIdentityListModel::EntryType>((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;i<mCategories.size();++i)
for(uint j=0;j<mCategories[i].child_identity_indices.size();++j)
if(mIdentities[mCategories[i].child_identity_indices[j]].id == id)
{
EntryIndex e;
e.category_index = i;
e.identity_index = j;
e.type = ENTRY_TYPE_IDENTITY;
quintptr idx;
convertIndexToInternalId(e,idx);
return createIndex(j,0,idx);
}
return QModelIndex();
}
QModelIndex RsIdentityListModel::getIndexOfCategory(Category id) const
{
EntryIndex e;
e.category_index = id;
e.type = ENTRY_TYPE_CATEGORY;
quintptr idx;
convertIndexToInternalId(e,idx);
return createIndex((int)id,0,idx);
}
QVariant RsIdentityListModel::foregroundRole(const EntryIndex& e, int /*col*/) const
{
auto it = getIdentityInfo(e);
if(!it)
return QVariant();
if(it->flags & 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<QTreeView*>(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 &it;
}
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<uint8_t>(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;j<mCategories.size();++j)
{
std::cerr << mCategories[j].category_name.toStdString() << " (" << mCategories[j].child_identity_indices.size() << ")" << std::endl;
const auto& hg(mCategories[j].child_identity_indices);
for(uint32_t i=0;i<hg.size();++i)
{
auto idx = getIndexOfIdentity(mIdentities[hg[i]].id);
auto parent = idx.parent();
EntryIndex index;
EntryIndex index_parent;
convertInternalIdToIndex(idx.internalId(),index);
convertInternalIdToIndex(parent.internalId(),index_parent);
std::cerr << " " << mIdentities[hg[i]].id << " index = " << idx << " parent = " << idx.parent() << " EntryIndex: " << index << " Parent index: " << index_parent << std::endl;
}
}
std::cerr << "====================================" << std::endl;
}
RsGxsId RsIdentityListModel::getIdentity(const QModelIndex& i) const
{
if(!i.isValid())
return RsGxsId();
EntryIndex e;
if(!convertInternalIdToIndex(i.internalId(),e) || e.type != ENTRY_TYPE_IDENTITY)
return RsGxsId();
const HierarchicalIdentityInformation *gnode = getIdentityInfo(e);
if(gnode)
return gnode->id;
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<RsGroupMetaData>& 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<RsGroupMetaData> 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));
}

View File

@ -1,252 +0,0 @@
/*******************************************************************************
* retroshare-gui/src/gui/msgs/RsFriendListModel.h *
* *
* Copyright 2019 by Cyril Soler <csoler@users.sourceforge.net> *
* *
* 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 <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <QModelIndex>
#include <QColor>
#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<uint32_t> 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<RsGroupMetaData>& 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<HierarchicalCategoryInformation> mCategories;
mutable std::vector<HierarchicalIdentityInformation> 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<EntryIndex> mTopLevel;
// keeps track of expanded/collapsed items, so as to only show icon for collapsed profiles
std::vector<bool> mExpandedCategories;
// List of identities for which getIdDetails() failed, to be requested again.
mutable QTimer *mIdentityUpdateTimer;
};

View File

@ -28,15 +28,9 @@
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
#include <QtDebug> #include <QtDebug>
#include <QMenuBar>
#include <retroshare/rsplugin.h> #include <retroshare/rsplugin.h>
#include <retroshare/rsconfig.h> #include <retroshare/rsconfig.h>
#include <util/argstream.h>
#if defined(Q_OS_DARWIN)
#include "gui/common/MacDockIconHandler.h"
#endif
#ifdef MESSENGER_WINDOW #ifdef MESSENGER_WINDOW
#include "MessengerWindow.h" #include "MessengerWindow.h"
@ -120,7 +114,7 @@
#include "gui/statistics/StatisticsWindow.h" #include "gui/statistics/StatisticsWindow.h"
#include "gui/connect/ConnectFriendWizard.h" #include "gui/connect/ConnectFriendWizard.h"
#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsCollection.h"
#include "settings/rsettingswin.h" #include "settings/rsettingswin.h"
#include "settings/rsharesettings.h" #include "settings/rsharesettings.h"
#include "common/StatusDefs.h" #include "common/StatusDefs.h"
@ -212,7 +206,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
hiddenmode = true; hiddenmode = true;
} }
setWindowTitle(tr("RetroShare %1 a secure decentralized communication platform").arg(RsApplication::retroshareVersion(true)) + " - " + nameAndLocation); setWindowTitle(tr("RetroShare %1 a secure decentralized communication platform").arg(Rshare::retroshareVersion(true)) + " - " + nameAndLocation);
connect(rApp, SIGNAL(newArgsReceived(QStringList)), this, SLOT(receiveNewArgs(QStringList))); connect(rApp, SIGNAL(newArgsReceived(QStringList)), this, SLOT(receiveNewArgs(QStringList)));
/* add url handler for RetroShare links */ /* add url handler for RetroShare links */
@ -360,8 +354,6 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
settingsChanged(); settingsChanged();
mFontSizeHandler.registerFontSize(ui->listWidget, 1.5f);
} }
/** Destructor. */ /** Destructor. */
@ -385,11 +377,6 @@ MainWindow::~MainWindow()
delete sysTrayStatus; delete sysTrayStatus;
delete trayIcon; delete trayIcon;
delete trayMenu; delete trayMenu;
#if defined(Q_OS_DARWIN)
delete menuBar;
delete dockMenu;
MacDockIconHandler::cleanup();
#endif
// delete notifyMenu; // already deleted by the deletion of trayMenu // delete notifyMenu; // already deleted by the deletion of trayMenu
StatisticsWindow::releaseInstance(); StatisticsWindow::releaseInstance();
@ -566,11 +553,6 @@ void MainWindow::addPage(MainPage *page, QActionGroup *grp, QList<QPair<MainPage
QListWidgetItem *item = new QListWidgetItem(QIcon(page->iconPixmap()),page->pageName()) ; QListWidgetItem *item = new QListWidgetItem(QIcon(page->iconPixmap()),page->pageName()) ;
ui->listWidget->addItem(item) ; ui->listWidget->addItem(item) ;
#if defined(Q_OS_DARWIN)
QFont f = ui->toolBarPage->font();
action->setFont(f);
#endif
if (notify) if (notify)
{ {
QPair<QAction*, QListWidgetItem*> pair = QPair<QAction*, QListWidgetItem*>( action, item); QPair<QAction*, QListWidgetItem*> pair = QPair<QAction*, QListWidgetItem*>( action, item);
@ -669,75 +651,10 @@ void MainWindow::createTrayIcon()
trayIcon->setContextMenu(trayMenu); trayIcon->setContextMenu(trayMenu);
trayIcon->setIcon(QIcon(IMAGE_NOONLINE)); trayIcon->setIcon(QIcon(IMAGE_NOONLINE));
#if defined(Q_OS_DARWIN)
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance();
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
show();
activateWindow();
});
#endif
#if defined(Q_OS_DARWIN)
createMenuBar();
#endif
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
trayIcon->show(); trayIcon->show();
} }
#if defined(Q_OS_DARWIN)
/** Creates a new menubar for macOS */
void MainWindow::createMenuBar()
{
/* Mac users sure like their shortcuts. */
actionMinimize = new QAction(tr("Minimize"),this);
actionMinimize->setShortcutContext(Qt::ApplicationShortcut);
actionMinimize->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
actionMinimize->setShortcutVisibleInContextMenu(true);
connect(actionMinimize,SIGNAL(triggered()),this,SLOT(minimizeWindow())) ;
actionCloseWindow = new QAction(tr("Close window"),this);
actionCloseWindow->setShortcutContext(Qt::ApplicationShortcut);
actionCloseWindow->setShortcut(QKeySequence::Close);
actionCloseWindow->setShortcutVisibleInContextMenu(true);
connect(actionCloseWindow,SIGNAL(triggered()),this,SLOT(closeWindow())) ;
menuBar = new QMenuBar(this);
QMenu *fileMenu = menuBar->addMenu("");
fileMenu->addAction(actionMinimize);
fileMenu->addAction(actionCloseWindow);
dockMenu = new QMenu(this);
dockMenu->setAsDockMenu();
dockMenu->addAction(tr("Open Messages"), this, SLOT(showMess()));
dockMenu->addAction(tr("Bandwidth Graph"), this, SLOT(showBandwidthGraph()));
dockMenu->addAction(tr("Statistics"), this, SLOT(showStatisticsWindow()));
dockMenu->addAction(tr("Options"), this, SLOT(showSettings()));
dockMenu->addAction(tr("Help"), this, SLOT(showHelpDialog()));
dockMenu->addSeparator();
QMenu *statusMenu = dockMenu->addMenu(tr("Status"));
initializeStatusObject(statusMenu, true);
}
#endif
#if defined(Q_OS_DARWIN)
void MainWindow::minimizeWindow()
{
setWindowState(windowState() | Qt::WindowMinimized);
}
#endif
#if defined(Q_OS_DARWIN)
void MainWindow::closeWindow()
{
// On macOS window close is basically equivalent to window hide.
close();
}
#endif
void MainWindow::showBandwidthGraph() void MainWindow::showBandwidthGraph()
{ {
if(_bandwidthGraph == NULL) if(_bandwidthGraph == NULL)
@ -1029,7 +946,6 @@ void SetForegroundWindowInternal(HWND hWnd)
/* Show the dialog. */ /* Show the dialog. */
raiseWindow(); raiseWindow();
/* Set the focus to the specified page. */ /* Set the focus to the specified page. */
_instance->ui->stackPages->setCurrentPage(page); _instance->ui->stackPages->setCurrentPage(page);
} }
@ -1262,91 +1178,10 @@ void MainWindow::doQuit()
rApp->quit(); rApp->quit();
} }
// This method parses arguments passed by the operating system. All arguments
// except -r, -f, -o and lists of rscollection files and rslinks are discarded.
//
void MainWindow::receiveNewArgs(QStringList args) void MainWindow::receiveNewArgs(QStringList args)
{ {
RsInfo() << "Received new arguments from operating system call."; Rshare::parseArguments(args, false);
processLastArgs();
std::string argstring = RsApplication::applicationFilePath().toStdString() ;
for(auto l:args)
argstring += " " + l.toStdString();
// This class does all the job at once: validate arguments, and parses them.
std::vector<std::string> links_and_files;
argstream as(argstring.c_str());
QString omValues = QString(";full;noturtle;gaming;minimal;");
std::string opModeStr;
std::string retroshare_link_url;
std::string rscollection_file;
as >> parameter('r',"rslink",retroshare_link_url,"Retroshare:// link","Retroshare link to open in Downloads " ,false)
>> parameter('f',"rsfile",rscollection_file,"file","File to open " ,false)
>> parameter('o',"opmode",opModeStr,"opmode","Set mode (Full, NoTurtle, Gaming, Minimal) " ,false)
>> values<std::string>(back_inserter(links_and_files),"links and files");
if(!as.isOk())
{
RsErr() << "Error while parsing arguments:" ;
RsErr() << as.errorLog() ;
return;
}
if(!opModeStr.empty() && omValues.contains(";"+QString::fromStdString(opModeStr).toLower()+";"))
{
QString opmode = QString::fromStdString(opModeStr).toLower();
//RsApplication::setOpMode(opModeStr.toLower()); // Do we need this??
RsInfo() << "Setting new operating mode to \"" << opmode.toStdString() << "\"";
if (opmode == "noturtle")
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::NOTURTLE) - 1);
else if (opmode == "gaming")
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::GAMING) - 1);
else if (opmode == "minimal")
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::MINIMAL) - 1);
else if (opmode != "")
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::FULL) - 1);
opModeStatus->setOpMode();
}
// Sort all collected arguments into rscollection files and retroshare links, accordingly
QStringList rscollection_files;
QList<RetroShareLink> rslinks;
auto sort = [&](const QString s) {
if(QFile(s).exists() && s.endsWith(".rscollection"))
rscollection_files.append(QString::fromUtf8(rscollection_file.c_str()));
else if(s.startsWith("retroshare://"))
{
RetroShareLink link(s);
if(link.valid())
rslinks.push_back(link);
}
};
sort(QString::fromUtf8(rscollection_file.c_str()));
sort(QString::fromUtf8(retroshare_link_url.c_str()));
for(auto s:links_and_files)
sort(QString::fromUtf8(s.c_str()));
// Now handle links and rscollection files.
for(auto file:rscollection_files)
if(file.endsWith(".rscollection"))
openRsCollection(file);
for(auto link:rslinks)
retroshareLinkActivated(link.toUrl());
} }
void MainWindow::displayErrorMessage(int /*a*/,int /*b*/,const QString& error_msg) void MainWindow::displayErrorMessage(int /*a*/,int /*b*/,const QString& error_msg)
@ -1385,11 +1220,7 @@ void MainWindow::updateMenu()
void MainWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e) void MainWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e)
{ {
#if defined(Q_OS_DARWIN)
if (e == QSystemTrayIcon::DoubleClick) {
#else
if (e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { if (e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) {
#endif
if (isHidden() || isMinimized()) { if (isHidden() || isMinimized()) {
show(); show();
if (isMinimized()) { if (isMinimized()) {
@ -1713,9 +1544,45 @@ void MainWindow::retroshareLinkActivated(const QUrl &url)
void MainWindow::openRsCollection(const QString &filename) void MainWindow::openRsCollection(const QString &filename)
{ {
QFileInfo qinfo(filename); QFileInfo qinfo(filename);
if (qinfo.exists()) {
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
RsCollection collection;
collection.openColl(qinfo.absoluteFilePath());
}
}
}
void MainWindow::processLastArgs()
{
while (!Rshare::links()->isEmpty()) {
std::cerr << "MainWindow::processLastArgs() : " << Rshare::links()->count() << std::endl;
/* Now use links from the command line, because no RetroShare was running */
RetroShareLink link(Rshare::links()->takeFirst());
if (link.valid()) {
retroshareLinkActivated(link.toUrl());
}
}
while (!Rshare::files()->isEmpty()) {
/* Now use files from the command line, because no RetroShare was running */
openRsCollection(Rshare::files()->takeFirst());
}
/* Handle the -opmode options. */
if (opModeStatus) {
QString opmode = Rshare::opmode().toLower();
if (opmode == "noturtle") {
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::NOTURTLE) - 1);
} else if (opmode == "gaming") {
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::GAMING) - 1);
} else if (opmode == "minimal") {
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::MINIMAL) - 1);
} else if (opmode != "") {
opModeStatus->setCurrentIndex(static_cast<typename std::underlying_type<RsOpMode>::type>(RsOpMode::FULL) - 1);
}
opModeStatus->setOpMode();
} else {
std::cerr << "ERR: MainWindow::processLastArgs opModeStatus is not initialized.";
}
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath());
} }
void MainWindow::switchVisibilityStatus(StatusElement e,bool b) void MainWindow::switchVisibilityStatus(StatusElement e,bool b)

View File

@ -27,7 +27,6 @@
#include "gui/common/rwindow.h" #include "gui/common/rwindow.h"
#include "gui/common/RSComboBox.h" #include "gui/common/RSComboBox.h"
#include "util/FontSizeHandler.h"
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@ -215,6 +214,7 @@ public slots:
void externalLinkActivated(const QUrl &url); void externalLinkActivated(const QUrl &url);
void retroshareLinkActivated(const QUrl &url); void retroshareLinkActivated(const QUrl &url);
void openRsCollection(const QString &filename); void openRsCollection(const QString &filename);
void processLastArgs();
//! Go to a specific part of the control panel. //! Go to a specific part of the control panel.
void setNewPage(int page); void setNewPage(int page);
void setCompactStatusMode(bool compact); void setCompactStatusMode(bool compact);
@ -265,11 +265,6 @@ private slots:
void toggleVisibility(QSystemTrayIcon::ActivationReason e); void toggleVisibility(QSystemTrayIcon::ActivationReason e);
void toggleVisibilitycontextmenu(); void toggleVisibilitycontextmenu();
#if defined(Q_OS_DARWIN)
void minimizeWindow();
void closeWindow();
#endif
/** Toolbar fns. */ /** Toolbar fns. */
void addFriend(); void addFriend();
//void newRsCollection(); //void newRsCollection();
@ -313,10 +308,6 @@ private:
void initStackedPage(); void initStackedPage();
void addPage(MainPage *page, QActionGroup *grp, QList<QPair<MainPage *, QPair<QAction *, QListWidgetItem *> > > *notify); void addPage(MainPage *page, QActionGroup *grp, QList<QPair<MainPage *, QPair<QAction *, QListWidgetItem *> > > *notify);
void createTrayIcon(); void createTrayIcon();
#if defined(Q_OS_DARWIN)
/** Creates a default menubar on Mac */
void createMenuBar();
#endif
void createNotifyIcons(); void createNotifyIcons();
static MainWindow *_instance; static MainWindow *_instance;
@ -333,14 +324,6 @@ private:
QString nameAndLocation; QString nameAndLocation;
#if defined(Q_OS_DARWIN)
/** The menubar (Mac OS X only). */
QMenuBar *menuBar;
QMenu *dockMenu;
QAction* actionMinimize;
QAction* actionCloseWindow;
#endif
QSystemTrayIcon *trayIcon; QSystemTrayIcon *trayIcon;
QMenu *notifyMenu; QMenu *notifyMenu;
QMenu *trayMenu; QMenu *trayMenu;
@ -372,8 +355,6 @@ private:
void setIdle(bool Idle); void setIdle(bool Idle);
bool isIdle; bool isIdle;
FontSizeHandler mFontSizeHandler;
Ui::MainWindow *ui ; Ui::MainWindow *ui ;
}; };

View File

@ -33,6 +33,11 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
@ -152,7 +157,7 @@
</action> </action>
<action name="actionOptions"> <action name="actionOptions">
<property name="icon"> <property name="icon">
<iconset> <iconset resource="images.qrc">
<normaloff>:/images/kcmsystem24.png</normaloff>:/images/kcmsystem24.png</iconset> <normaloff>:/images/kcmsystem24.png</normaloff>:/images/kcmsystem24.png</iconset>
</property> </property>
<property name="text"> <property name="text">

View File

@ -41,7 +41,7 @@
PluginManager::PluginManager() PluginManager::PluginManager()
{ {
baseFolder = //qApp->applicationDirPath()+"///plugins" ; baseFolder = //qApp->applicationDirPath()+"///plugins" ;
RsApplication::dataDirectory() + "/plugins" ; Rshare::dataDirectory() + "/plugins" ;
lastError = "No error."; lastError = "No error.";
viewWidget = 0; viewWidget = 0;

View File

@ -22,6 +22,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>MS Sans Serif</family> <family>MS Sans Serif</family>
<pointsize>11</pointsize>
<weight>75</weight> <weight>75</weight>
<italic>true</italic> <italic>true</italic>
<bold>true</bold> <bold>true</bold>
@ -102,6 +103,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>MS Sans Serif</family> <family>MS Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight> <weight>50</weight>
<bold>false</bold> <bold>false</bold>
</font> </font>
@ -112,7 +114,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="AvatarWidget" name="avatarWidget"> <widget class="AvatarWidget" name="avatarWidget" native="true">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>24</width> <width>24</width>
@ -132,6 +134,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>MS Sans Serif</family> <family>MS Sans Serif</family>
<pointsize>11</pointsize>
<weight>75</weight> <weight>75</weight>
<italic>true</italic> <italic>true</italic>
<bold>true</bold> <bold>true</bold>
@ -147,6 +150,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>MS Sans Serif</family> <family>MS Sans Serif</family>
<pointsize>9</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -159,6 +163,7 @@
<property name="font"> <property name="font">
<font> <font>
<family>MS Sans Serif</family> <family>MS Sans Serif</family>
<pointsize>9</pointsize>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
@ -204,17 +209,17 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>AvatarWidget</class>
<extends>QLabel</extends>
<header>gui/common/AvatarWidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>GxsIdLabel</class> <class>GxsIdLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header> <header>gui/gxs/GxsIdLabel.h</header>
</customwidget> </customwidget>
<customwidget>
<class>AvatarWidget</class>
<extends>QWidget</extends>
<header>gui/common/AvatarWidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>AspectRatioPixmapLabel</class> <class>AspectRatioPixmapLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>

View File

@ -262,6 +262,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize>
<weight>75</weight> <weight>75</weight>
<italic>true</italic> <italic>true</italic>
<bold>true</bold> <bold>true</bold>
@ -725,17 +726,17 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
<customwidget> <customwidget>
<class>ElidedLabel</class> <class>ElidedLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>
<header>gui/common/ElidedLabel.h</header> <header>gui/common/ElidedLabel.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
<customwidget> <customwidget>
<class>ZoomableLabel</class> <class>ZoomableLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>
@ -743,9 +744,9 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../icons.qrc"/>
<include location="Posted_images.qrc"/>
<include location="../images.qrc"/> <include location="../images.qrc"/>
<include location="Posted_images.qrc"/>
<include location="../icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -619,13 +619,12 @@ void PostedListWidgetWithModel::updateGroupData()
void PostedListWidgetWithModel::postPostLoad() void PostedListWidgetWithModel::postPostLoad()
{ {
#ifdef DEBUG_POSTED
std::cerr << "Post channel load..." << std::endl; std::cerr << "Post channel load..." << std::endl;
#endif
whileBlocking(ui->filter_LE)->setText(QString()); //Clear it before navigate, as it will update it. whileBlocking(ui->filter_LE)->setText(QString()); //Clear it before navigate, as it will update it.
if (!mNavigatePendingMsgId.isNull()) if (!mNavigatePendingMsgId.isNull())
navigate(mNavigatePendingMsgId); navigate(mNavigatePendingMsgId);
#ifdef TO_REMOVE #ifdef TO_REMOVE
else if( (mLastSelectedPosts.count(groupId()) > 0) else if( (mLastSelectedPosts.count(groupId()) > 0)
&& !mLastSelectedPosts[groupId()].isNull()) && !mLastSelectedPosts[groupId()].isNull())
@ -640,10 +639,8 @@ void PostedListWidgetWithModel::postPostLoad()
ui->postsTree->setFocus(); ui->postsTree->setFocus();
} }
#endif #endif
#ifdef DEBUG_POSTED
else else
std::cerr << "No pre-selected channel post." << std::endl; std::cerr << "No pre-selected channel post." << std::endl;
#endif
updateShowLabel(); updateShowLabel();
} }

View File

@ -54,7 +54,7 @@
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;Description&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="textInteractionFlags"> <property name="textInteractionFlags">
@ -355,10 +355,10 @@ p, li { white-space: pre-wrap; }
<item> <item>
<widget class="QFrame" name="toolBarFrame"> <widget class="QFrame" name="toolBarFrame">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin"> <property name="leftMargin">
@ -576,10 +576,37 @@ p, li { white-space: pre-wrap; }
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>ElidedLabel</class>
<extends>QLabel</extends>
<header>gui/common/ElidedLabel.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GxsIdChooser</class>
<extends>QComboBox</extends>
<header>gui/gxs/GxsIdChooser.h</header>
</customwidget>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
<customwidget> <customwidget>
<class>LineEditClear</class> <class>LineEditClear</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header location="global">gui/common/LineEditClear.h</header> <header>gui/common/LineEditClear.h</header>
</customwidget>
<customwidget>
<class>RSComboBox</class>
<extends>QComboBox</extends>
<header>gui/common/RSComboBox.h</header>
</customwidget>
<customwidget>
<class>RSTabWidget</class>
<extends>QTabWidget</extends>
<header>gui/common/RSTabWidget.h</header>
<container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>RSTreeView</class> <class>RSTreeView</class>
@ -587,42 +614,15 @@ p, li { white-space: pre-wrap; }
<header>gui/common/RSTreeView.h</header> <header>gui/common/RSTreeView.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
<customwidget>
<class>ElidedLabel</class>
<extends>QLabel</extends>
<header>gui/common/ElidedLabel.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>SubscribeToolButton</class> <class>SubscribeToolButton</class>
<extends>QToolButton</extends> <extends>QToolButton</extends>
<header>gui/common/SubscribeToolButton.h</header> <header>gui/common/SubscribeToolButton.h</header>
</customwidget> </customwidget>
<customwidget>
<class>RSComboBox</class>
<extends>QComboBox</extends>
<header>gui/common/RSComboBox.h</header>
</customwidget>
<customwidget>
<class>GxsIdChooser</class>
<extends>QComboBox</extends>
<header>gui/gxs/GxsIdChooser.h</header>
</customwidget>
<customwidget>
<class>RSTabWidget</class>
<extends>QTabWidget</extends>
<header>gui/common/RSTabWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../icons.qrc"/>
<include location="Posted_images.qrc"/> <include location="Posted_images.qrc"/>
<include location="../icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -88,16 +88,11 @@ class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate
public: public:
virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const
{ {
painter->save();
QStyleOptionViewItem opt(option) ; QStyleOptionViewItem opt(option) ;
setPainterOptions(painter,opt,index) ; setPainterOptions(painter,opt,index) ;
if(index.data().toLongLong() > 0) { // no date is present. if(index.data().toLongLong() > 0) // no date is present.
painter->setFont(opt.font); painter->drawText(opt.rect, Qt::AlignCenter, misc::timeRelativeToNow(index.data().toLongLong())) ;
painter->drawText(opt.rect, opt.displayAlignment, misc::timeRelativeToNow(index.data().toLongLong())) ;
}
painter->restore();
} }
}; };
@ -106,14 +101,10 @@ class RSHumanReadableSizeDelegate: public RSHumanReadableDelegate
public: public:
virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const
{ {
painter->save();
QStyleOptionViewItem opt(option) ; QStyleOptionViewItem opt(option) ;
setPainterOptions(painter,opt,index) ; setPainterOptions(painter,opt,index) ;
painter->setFont(opt.font); painter->drawText(opt.rect, Qt::AlignRight, misc::friendlyUnit(index.data().toULongLong()));
painter->drawText(opt.rect, opt.displayAlignment, misc::friendlyUnit(index.data().toULongLong()));
painter->restore();
} }
}; };

View File

@ -24,7 +24,7 @@
#include "gui/common/FilesDefs.h" #include "gui/common/FilesDefs.h"
#include "gui/common/GroupDefs.h" #include "gui/common/GroupDefs.h"
#include "gui/common/RsCollectionDialog.h" #include "gui/common/RsCollection.h"
#include "gui/common/RsUrlHandler.h" #include "gui/common/RsUrlHandler.h"
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
#include "retroshare/rsfiles.h" #include "retroshare/rsfiles.h"
@ -1233,6 +1233,31 @@ bool RetroshareDirModel::requestDirDetails(void *ref, bool remote,DirDetails& d)
return false ; return false ;
} }
void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndexList &list)
{
/* if(RemoteMode)
{
std::cerr << "Cannot create a collection file from remote" << std::endl;
return ;
}*/
std::vector <DirDetails> dirVec;
getDirDetailsFromSelect(list, dirVec);
FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
QString dir_name;
if(!RemoteMode)
{
if(!dirVec.empty())
{
const DirDetails& details = dirVec[0];
dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
}
}
RsCollection(dirVec,f).openNewColl(parent,dir_name);
}
void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool interactive) void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool interactive)
{ {
if (!RemoteMode) if (!RemoteMode)
@ -1253,7 +1278,7 @@ void RetroshareDirModel::downloadSelected(const QModelIndexList &list,bool inter
FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ; FileSearchFlags f = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
if(interactive) if(interactive)
RsCollectionDialog::downloadFiles(RsCollection(dirVec,f)) ; RsCollection(dirVec,f).downloadFiles() ;
else /* Fire off requests */ else /* Fire off requests */
for (int i = 0, n = dirVec.size(); i < n; ++i) for (int i = 0, n = dirVec.size(); i < n; ++i)
{ {

View File

@ -68,6 +68,8 @@ class RetroshareDirModel : public QAbstractItemModel
/* Callback from GUI */ /* Callback from GUI */
void downloadSelected(const QModelIndexList &list, bool interactive); void downloadSelected(const QModelIndexList &list, bool interactive);
void createCollectionFile(QWidget *parent, const QModelIndexList &list);
void getDirDetailsFromSelect (const QModelIndexList &list, std::vector <DirDetails>& dirVec); void getDirDetailsFromSelect (const QModelIndexList &list, std::vector <DirDetails>& dirVec);
int getType ( const QModelIndex & index ) const ; int getType ( const QModelIndex & index ) const ;

View File

@ -25,7 +25,7 @@
#include "HomePage.h" #include "HomePage.h"
#include "chat/ChatDialog.h" #include "chat/ChatDialog.h"
#include "common/PeerDefs.h" #include "common/PeerDefs.h"
#include "common/RsCollectionDialog.h" #include "common/RsCollection.h"
#include "common/RsUrlHandler.h" #include "common/RsUrlHandler.h"
#include "connect/ConfCertDialog.h" #include "connect/ConfCertDialog.h"
#include "connect/ConnectFriendWizard.h" #include "connect/ConnectFriendWizard.h"
@ -1143,15 +1143,13 @@ QString RetroShareLink::toHtmlSize() const
if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) { if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) {
FileInfo finfo; FileInfo finfo;
if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) {
{ RsCollection collection;
RsCollection::RsCollectionErrorCode code; if (collection.load(QString::fromUtf8(finfo.path.c_str()), false)) {
RsCollection collection(QString::fromUtf8(finfo.path.c_str()), code) ;
if(code == RsCollection::RsCollectionErrorCode::COLLECTION_NO_ERROR)
size += QString(" [%1]").arg(misc::friendlyUnit(collection.size())); size += QString(" [%1]").arg(misc::friendlyUnit(collection.size()));
} }
} }
}
QString link = QString("<a href=\"%1\">%2</a> <font color=\"blue\">%3</font>").arg(toString()).arg(name()).arg(size); QString link = QString("<a href=\"%1\">%2</a> <font color=\"blue\">%3</font>").arg(toString()).arg(name()).arg(size);
return link; return link;
} }
@ -1724,8 +1722,9 @@ static void processList(const QStringList &list, const QString &textSingular, co
case TYPE_FILE_TREE: case TYPE_FILE_TREE:
{ {
auto ft = RsFileTree::fromRadix64(link.radix().toStdString() ); auto ft = RsFileTree::fromRadix64(
RsCollectionDialog::downloadFiles(RsCollection(*ft)); link.radix().toStdString() );
RsCollection(*ft).downloadFiles();
break; break;
} }
@ -1777,7 +1776,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
// were single file links found? // were single file links found?
if (fileLinkFound) if (fileLinkFound)
RsCollectionDialog::downloadFiles(col); col.downloadFiles();
int countProcessed = 0; int countProcessed = 0;
int countError = 0; int countError = 0;
@ -1920,9 +1919,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
void RSLinkClipboard::copyLinks(const QList<RetroShareLink>& links) void RSLinkClipboard::copyLinks(const QList<RetroShareLink>& links)
{ {
QString res ; QString res ;
if(links.size() == 1) for (int i = 0; i < links.size(); ++i)
res += links[0].toString();
else for(int i = 0; i < links.size(); ++i)
res += links[i].toString() + "\n" ; res += links[i].toString() + "\n" ;
QApplication::clipboard()->setText(res) ; QApplication::clipboard()->setText(res) ;
@ -2038,3 +2035,4 @@ void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links,Retro
pos += rx.matchedLength(); pos += rx.matchedLength();
} }
} }

View File

@ -123,7 +123,7 @@ void StartDialog::loadPerson()
rsNotify->cachePgpPassphrase(ui.password_input->text().toUtf8().constData()) ; rsNotify->cachePgpPassphrase(ui.password_input->text().toUtf8().constData()) ;
rsNotify->setDisableAskPassword(true); rsNotify->setDisableAskPassword(true);
bool res = RsApplication::loadCertificate(accountId, ui.autologin_checkbox->isChecked()) ; bool res = Rshare::loadCertificate(accountId, ui.autologin_checkbox->isChecked()) ;
rsNotify->setDisableAskPassword(false); rsNotify->setDisableAskPassword(false);
rsNotify->clearPgpPassphrase(); rsNotify->clearPgpPassphrase();
@ -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); 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 #else
// this handles all linux systems at once. // 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 desktop's 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 Gnome Keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok);
#endif #endif
#endif #endif
} }

View File

@ -345,8 +345,8 @@ The current identities/locations will not be affected.</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;Create new Profile...&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:14pt; text-decoration: underline; color:#0000ff;&quot;&gt;New Profile/Node&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;Create new Profile...&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;New Profile/Node&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -370,8 +370,8 @@ p, li { white-space: pre-wrap; }
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="icons.qrc"/>
<include location="images.qrc"/> <include location="images.qrc"/>
<include location="icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -25,7 +25,6 @@
#include "gui/gxs/GxsIdDetails.h" #include "gui/gxs/GxsIdDetails.h"
#include "gui/common/FilesDefs.h" #include "gui/common/FilesDefs.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/qtthreadsutils.h"
#include "PulseAddDialog.h" #include "PulseAddDialog.h"
@ -99,31 +98,11 @@ void PulseAddDialog::setGroup(RsWireGroup &group)
// set ReplyWith Group. // set ReplyWith Group.
void PulseAddDialog::setGroup(const RsGxsGroupId &grpId) void PulseAddDialog::setGroup(const RsGxsGroupId &grpId)
{ {
if(grpId.isNull()){ /* fetch in the background */
return;
}
RsThread::async([this,grpId](){
RsWireGroupSPtr pGroup; RsWireGroupSPtr pGroup;
if(!rsWire->getWireGroup(grpId,pGroup)) rsWire->getWireGroup(grpId, pGroup);
{
std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve wire group info for wire id: " << grpId << std::endl;
return;
}
RsQThreadUtils::postToObject( [pGroup,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, note that
* Qt::QueuedConnection is important!
*/
setGroup(*pGroup); setGroup(*pGroup);
}, this );
});
} }
void PulseAddDialog::cleanup() void PulseAddDialog::cleanup()
@ -215,7 +194,7 @@ void PulseAddDialog::setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse
mReplyToPulse = pulse; mReplyToPulse = pulse;
mReplyType = replyType; mReplyType = replyType;
ui.frame_reply->setVisible(true); ui.frame_reply->setVisible(true);
ui.pushButton_picture->hide(); ui.pushButton_picture->show();
ui.topheadshot->hide(); ui.topheadshot->hide();
{ {
@ -244,12 +223,10 @@ void PulseAddDialog::setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse
if (mReplyType & WIRE_PULSE_TYPE_REPUBLISH) { if (mReplyType & WIRE_PULSE_TYPE_REPUBLISH) {
ui.postButton->setText(tr("Republish Pulse")); ui.postButton->setText(tr("Republish Pulse"));
ui.pushButton_picture->hide(); ui.pushButton_picture->hide();
ui.pushButton_Browse->hide();
} }
else if (mReplyType & WIRE_PULSE_TYPE_LIKE) { else if (mReplyType & WIRE_PULSE_TYPE_LIKE) {
ui.postButton->setText(tr("Like Pulse")); ui.postButton->setText(tr("Like Pulse"));
ui.pushButton_picture->hide(); ui.pushButton_picture->hide();
ui.pushButton_Browse->hide();
} }
} }
@ -257,24 +234,20 @@ void PulseAddDialog::setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse
void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, uint32_t replyType) void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, uint32_t replyType)
{ {
if(grpId.isNull()){
return;
}
/* fetch in the background */ /* fetch in the background */
RsThread::async([this,grpId,msgId,replyType](){
RsWireGroupSPtr pGroup; RsWireGroupSPtr pGroup;
RsWirePulseSPtr pPulse; if (!rsWire->getWireGroup(grpId, pGroup))
if(!rsWire->getWireGroup(grpId,pGroup))
{ {
std::cerr << __PRETTY_FUNCTION__ << "PulseAddDialog::setRplyTo() failed to fetch group id: " << grpId << std::endl; std::cerr << "PulseAddDialog::setRplyTo() failed to fetch group";
std::cerr << std::endl;
return; return;
} }
RsWirePulseSPtr pPulse;
if (!rsWire->getWirePulse(grpId, msgId, pPulse)) if (!rsWire->getWirePulse(grpId, msgId, pPulse))
{ {
std::cerr << "PulseAddDialog::setRplyTo() failed to fetch pulse of group id: " << grpId << std::endl; std::cerr << "PulseAddDialog::setRplyTo() failed to fetch pulse";
std::cerr << std::endl;
return; return;
} }
@ -284,19 +257,7 @@ void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId
pPulse->mGroupPtr = pGroup; pPulse->mGroupPtr = pGroup;
} }
RsQThreadUtils::postToObject( [pGroup,this,pPulse,replyType]()
{
/* 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, note that
* Qt::QueuedConnection is important!
*/
setReplyTo(*pPulse, pPulse, pGroup->mMeta.mGroupName, replyType); setReplyTo(*pPulse, pPulse, pGroup->mMeta.mGroupName, replyType);
}, this );
});
} }
void PulseAddDialog::addURL() void PulseAddDialog::addURL()
@ -356,8 +317,7 @@ void PulseAddDialog::postOriginalPulse()
pPulse->mImage3 = mImage3; pPulse->mImage3 = mImage3;
pPulse->mImage4 = mImage4; pPulse->mImage4 = mImage4;
RsThread::async([this,pPulse](){ // this should be in async thread, so doesn't block UI thread.
if (!rsWire->createOriginalPulse(mGroup.mMeta.mGroupId, pPulse)) if (!rsWire->createOriginalPulse(mGroup.mMeta.mGroupId, pPulse))
{ {
std::cerr << "PulseAddDialog::postOriginalPulse() FAILED"; std::cerr << "PulseAddDialog::postOriginalPulse() FAILED";
@ -365,20 +325,8 @@ void PulseAddDialog::postOriginalPulse()
return; return;
} }
RsQThreadUtils::postToObject( [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, note that
* Qt::QueuedConnection is important!
*/
clearDialog(); clearDialog();
hide(); hide();
}, this );
});
} }
uint32_t PulseAddDialog::toPulseSentiment(int index) uint32_t PulseAddDialog::toPulseSentiment(int index)
@ -430,8 +378,7 @@ void PulseAddDialog::postReplyPulse()
pPulse->mImage4 = mReplyToPulse.mImage4; pPulse->mImage4 = mReplyToPulse.mImage4;
} }
RsThread::async([this, pPulse](){ // this should be in async thread, so doesn't block UI thread.
if (!rsWire->createReplyPulse(mReplyToPulse.mMeta.mGroupId, if (!rsWire->createReplyPulse(mReplyToPulse.mMeta.mGroupId,
mReplyToPulse.mMeta.mOrigMsgId, mReplyToPulse.mMeta.mOrigMsgId,
mGroup.mMeta.mGroupId, mGroup.mMeta.mGroupId,
@ -443,20 +390,8 @@ void PulseAddDialog::postReplyPulse()
return; return;
} }
RsQThreadUtils::postToObject( [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, note that
* Qt::QueuedConnection is important!
*/
clearDialog(); clearDialog();
hide(); hide();
}, this );
});
} }
void PulseAddDialog::clearDialog() void PulseAddDialog::clearDialog()

View File

@ -140,7 +140,7 @@
<widget class="QWidget" name="widget_sentiment" native="true"> <widget class="QWidget" name="widget_sentiment" native="true">
<layout class="QHBoxLayout" name="widget_sentiment_HL"> <layout class="QHBoxLayout" name="widget_sentiment_HL">
<property name="leftMargin"> <property name="leftMargin">
<number>9</number> <number>20</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>

View File

@ -40,7 +40,10 @@
</size> </size>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true">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}</string>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>

View File

@ -140,7 +140,6 @@ WireDialog::~WireDialog()
processSettings(false); processSettings(false);
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::~WireDialog()" << std::endl;
delete(mWireQueue); delete(mWireQueue);
rsEvents->unregisterEventsHandler(mEventHandlerId); rsEvents->unregisterEventsHandler(mEventHandlerId);
@ -155,16 +154,9 @@ void WireDialog::processSettings(bool load)
// state of splitter // state of splitter
ui.splitter->restoreState(Settings->value("SplitterWire").toByteArray()); ui.splitter->restoreState(Settings->value("SplitterWire").toByteArray());
// state of filter combobox
int index = Settings->value("ShowGroup", 0).toInt();
ui.comboBox_groupSet->setCurrentIndex(index);
} else { } else {
// save settings // save settings
// state of filter combobox
Settings->setValue("ShowGroup", ui.comboBox_groupSet->currentIndex());
// state of splitter // state of splitter
Settings->setValue("SplitterWire", ui.splitter->saveState()); Settings->setValue("SplitterWire", ui.splitter->saveState());
} }
@ -689,7 +681,6 @@ void WireDialog::PVHrate(const RsGxsId &authorId)
void WireDialog::postTestTwitterView() void WireDialog::postTestTwitterView()
{ {
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::postTestTwitterView()" << std::endl;
addTwitterView(new PulseTopLevel(NULL,RsWirePulseSPtr())); addTwitterView(new PulseTopLevel(NULL,RsWirePulseSPtr()));
addTwitterView(new PulseReply(NULL,RsWirePulseSPtr())); addTwitterView(new PulseReply(NULL,RsWirePulseSPtr()));
@ -846,7 +837,6 @@ void WireDialog::requestPulseFocus(const RsGxsGroupId groupId, const RsGxsMessag
void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId msgId) void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId msgId)
{ {
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::showPulseFocus()" << std::endl;
// background thread for loading. // background thread for loading.
RsThread::async([this, groupId, msgId]() RsThread::async([this, groupId, msgId]()
@ -876,8 +866,6 @@ void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId
void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse) void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse)
{ {
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::postPulseFocus()" << std::endl;
if (!pPulse) if (!pPulse)
{ {
std::cerr << "WireDialog::postPulseFocus() Invalid pulse"; std::cerr << "WireDialog::postPulseFocus() Invalid pulse";
@ -950,7 +938,7 @@ void WireDialog::requestGroupFocus(const RsGxsGroupId groupId)
void WireDialog::showGroupFocus(const RsGxsGroupId groupId) void WireDialog::showGroupFocus(const RsGxsGroupId groupId)
{ {
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::showGroupFocus()" << std::endl;
// background thread for loading. // background thread for loading.
RsThread::async([this, groupId]() RsThread::async([this, groupId]()
{ {
@ -1027,7 +1015,6 @@ void WireDialog::requestGroupsPulses(const std::list<RsGxsGroupId>& groupIds)
void WireDialog::showGroupsPulses(const std::list<RsGxsGroupId>& groupIds) void WireDialog::showGroupsPulses(const std::list<RsGxsGroupId>& groupIds)
{ {
clearTwitterView(); clearTwitterView();
std::cerr << "WireDialog::showGroupPulses()" << std::endl;
// background thread for loading. // background thread for loading.
RsThread::async([this, groupIds]() RsThread::async([this, groupIds]()
@ -1077,3 +1064,4 @@ void WireDialog::postGroupsPulses(std::list<RsWirePulseSPtr> pulses)
} }
} }

View File

@ -123,21 +123,21 @@ void WireGroupItem::setup()
void WireGroupItem::setGroupSet() void WireGroupItem::setGroupSet()
{ {
if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) {
toolButton_type->setText(tr("Own")); toolButton_type->setText("Own");
toolButton_subscribe->setText(tr("N/A")); toolButton_subscribe->setText("N/A");
toolButton_subscribe->setEnabled(false); toolButton_subscribe->setEnabled(false);
editButton->show(); editButton->show();
} }
else if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) else if (mGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)
{ {
toolButton_type->setText(tr("Following")); toolButton_type->setText("Following");
toolButton_subscribe->setText(tr("Unfollow")); toolButton_subscribe->setText("Unfollow");
editButton->hide(); editButton->hide();
} }
else else
{ {
toolButton_type->setText(tr("Other")); toolButton_type->setText("Other");
toolButton_subscribe->setText(tr("Follow")); toolButton_subscribe->setText("Follow");
editButton->hide(); editButton->hide();
} }
} }

View File

@ -208,8 +208,6 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
connect(unsubscribeButton, SIGNAL(clicked()), this , SLOT(leaveLobby())); connect(unsubscribeButton, SIGNAL(clicked()), this , SLOT(leaveLobby()));
getChatWidget()->addTitleBarWidget(unsubscribeButton) ; getChatWidget()->addTitleBarWidget(unsubscribeButton) ;
mFontSizeHandler.registerFontSize(ui.participantsList);
} }
void ChatLobbyDialog::leaveLobby() void ChatLobbyDialog::leaveLobby()

View File

@ -26,7 +26,6 @@
#include "gui/common/RSTreeWidgetItem.h" #include "gui/common/RSTreeWidgetItem.h"
#include "ChatDialog.h" #include "ChatDialog.h"
#include "PopupChatWindow.h" #include "PopupChatWindow.h"
#include "util/FontSizeHandler.h"
// Q_DECLARE_METATYPE(RsGxsId) // Q_DECLARE_METATYPE(RsGxsId)
// Q_DECLARE_METATYPE(QList<RsGxsId>) // Q_DECLARE_METATYPE(QList<RsGxsId>)
@ -116,8 +115,6 @@ private:
bool mWindowedSetted; bool mWindowedSetted;
PopupChatWindow* mPCWindow; PopupChatWindow* mPCWindow;
FontSizeHandler mFontSizeHandler;
/** Qt Designer generated object */ /** Qt Designer generated object */
Ui::ChatLobbyDialog ui; Ui::ChatLobbyDialog ui;

View File

@ -146,48 +146,8 @@ QString ChatLobbyUserNotify::getNotifyMessage(bool plural)
void ChatLobbyUserNotify::iconClicked() void ChatLobbyUserNotify::iconClicked()
{ {
#if defined(Q_OS_DARWIN)
std::list<ChatLobbyId> lobbies;
rsMsgs->getChatLobbyList(lobbies);
bool doUpdate=false;
for (lobby_map::iterator itCL=_listMsg.begin(); itCL!=_listMsg.end();)
{
bool bFound=false;
QString strLobbyName=tr("Unknown Lobby");
QIcon icoLobby=QIcon();
std::list<ChatLobbyId>::const_iterator lobbyIt;
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
ChatLobbyId clId = *lobbyIt;
if (clId==itCL->first) {
ChatLobbyInfo clInfo;
if (rsMsgs->getChatLobbyInfo(clId,clInfo))
strLobbyName=QString::fromUtf8(clInfo.lobby_name.c_str()) ;
bFound=true;
break;
}
}
if (bFound)
{
MainWindow::showWindow(MainWindow::ChatLobby);
ChatLobbyWidget *chatLobbyWidget = dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby));
if (chatLobbyWidget) chatLobbyWidget->showLobbyAnchor(itCL->first,strLobbyName);
++itCL ;
}
else
{
lobby_map::iterator ittmp(itCL);
++ittmp ;
_listMsg.erase(itCL);
itCL=ittmp ;
doUpdate=true;
}
}
#else
/// Tray icon Menu /// /// Tray icon Menu ///
QMenu* trayMenu = createMenu(); QMenu* trayMenu = new QMenu(MainWindow::getInstance());
std::list<ChatLobbyId> lobbies; std::list<ChatLobbyId> lobbies;
rsMsgs->getChatLobbyList(lobbies); rsMsgs->getChatLobbyList(lobbies);
bool doUpdate=false; bool doUpdate=false;
@ -226,25 +186,27 @@ void ChatLobbyUserNotify::iconClicked()
} }
} }
if (notifyCombined()) {
QSystemTrayIcon* trayIcon=getTrayIcon();
if (trayIcon!=NULL) trayIcon->setContextMenu(trayMenu);
} else {
QAction* action=getNotifyIcon();
if (action!=NULL) {
action->setMenu(trayMenu);
}
}
QString strName=tr("Remove All"); QString strName=tr("Remove All");
QAction *pAction = new QAction( QIcon(), strName, trayMenu); QAction *pAction = new QAction( QIcon(), strName, trayMenu);
ActionTag actionTag={0x0, "", true}; ActionTag actionTag={0x0, "", true};
pAction->setData(qVariantFromValue(actionTag)); pAction->setData(qVariantFromValue(actionTag));
connect(trayMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*)));
connect(trayMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*)));
trayMenu->addAction(pAction); trayMenu->addAction(pAction);
trayMenu->exec(QCursor::pos()); trayMenu->exec(QCursor::pos());
delete(trayMenu);
if (doUpdate) updateIcon(); if (doUpdate) updateIcon();
#endif
}
QMenu* ChatLobbyUserNotify::createMenu()
{
QMenu* menu = new QMenu(MainWindow::getInstance());
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*)));
connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*)));
return menu;
} }
void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id) void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id)
@ -255,7 +217,11 @@ void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString
unsigned int msgCount=msgMap.size(); unsigned int msgCount=msgMap.size();
if(!parentMenu) parentMenu = new QMenu(MainWindow::getInstance());
QMenu *lobbyMenu = parentMenu->addMenu(icoLobby, strLobbyName); QMenu *lobbyMenu = parentMenu->addMenu(icoLobby, strLobbyName);
connect(lobbyMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*)));
connect(lobbyMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*)));
lobbyMenu->setToolTip(getNotifyMessage(msgCount>1).arg(msgCount)); lobbyMenu->setToolTip(getNotifyMessage(msgCount>1).arg(msgCount));
for (msg_map::iterator itMsg=msgMap.begin(); itMsg!=msgMap.end(); ++itMsg) { for (msg_map::iterator itMsg=msgMap.begin(); itMsg!=msgMap.end(); ++itMsg) {
@ -277,6 +243,7 @@ void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString
ActionTag actionTag={itCL->first, "", true}; ActionTag actionTag={itCL->first, "", true};
pAction->setData(qVariantFromValue(actionTag)); pAction->setData(qVariantFromValue(actionTag));
lobbyMenu->addAction(pAction); lobbyMenu->addAction(pAction);
} }
void ChatLobbyUserNotify::iconHovered() void ChatLobbyUserNotify::iconHovered()
@ -284,6 +251,7 @@ void ChatLobbyUserNotify::iconHovered()
iconClicked(); iconClicked();
} }
void ChatLobbyUserNotify::chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg) void ChatLobbyUserNotify::chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg)
{ {

View File

@ -49,7 +49,6 @@ public:
ChatLobbyUserNotify(QObject *parent = 0); ChatLobbyUserNotify(QObject *parent = 0);
virtual bool hasSetting(QString *name, QString *group); virtual bool hasSetting(QString *name, QString *group);
QMenu* createMenu();
void makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id); void makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id);
void chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg); void chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg);
void chatLobbyCleared(ChatLobbyId lobby_id, QString anchor, bool onlyUnread=false); void chatLobbyCleared(ChatLobbyId lobby_id, QString anchor, bool onlyUnread=false);

View File

@ -76,7 +76,7 @@ bool ChatUserNotify::hasSetting(QString *name, QString *group)
QIcon ChatUserNotify::getIcon() QIcon ChatUserNotify::getIcon()
{ {
return FilesDefs::getIconFromQtResourcePath(":/images/orange-bubble-64.png"); return FilesDefs::getIconFromQtResourcePath(":/images/chat.png");
} }
QIcon ChatUserNotify::getMainIcon(bool hasNew) QIcon ChatUserNotify::getMainIcon(bool hasNew)

View File

@ -982,12 +982,11 @@ void ChatWidget::on_notifyButton_clicked()
if(!notify) return; if(!notify) return;
if (chatType() != CHATTYPE_LOBBY) return; if (chatType() != CHATTYPE_LOBBY) return;
QMenu* menu = notify->createMenu(); QMenu* menu = new QMenu(MainWindow::getInstance());
QIcon icoLobby=(ui->notifyButton->icon()); QIcon icoLobby=(ui->notifyButton->icon());
notify->makeSubMenu(menu, icoLobby, title, chatId.toLobbyId()); notify->makeSubMenu(menu, icoLobby, title, chatId.toLobbyId());
menu->exec(ui->notifyButton->mapToGlobal(QPoint(0,ui->notifyButton->geometry().height()))); menu->exec(ui->notifyButton->mapToGlobal(QPoint(0,ui->notifyButton->geometry().height())));
delete(menu);
} }

View File

@ -54,9 +54,7 @@ bool AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
/* get avatar */ /* get avatar */
rsMsgs->getAvatarData(RsPeerId(sslId), data, size); rsMsgs->getAvatarData(RsPeerId(sslId), data, size);
if (size == 0) { if (size == 0) {
if (!defaultImage.isEmpty()) {
avatar = FilesDefs::getPixmapFromQtResourcePath(defaultImage); avatar = FilesDefs::getPixmapFromQtResourcePath(defaultImage);
}
return false; return false;
} }

View File

@ -121,7 +121,7 @@ void AvatarWidget::setFrameType(FrameType type)
//refreshAvatarImage(); //refreshAvatarImage();
refreshStatus(); refreshStatus();
RsApplication::refreshStyleSheet(this, false); Rshare::refreshStyleSheet(this, false);
} }
void AvatarWidget::setId(const ChatId &id) void AvatarWidget::setId(const ChatId &id)
{ {
@ -174,7 +174,7 @@ void AvatarWidget::refreshStatus()
case NO_FRAME: case NO_FRAME:
case NORMAL_FRAME: case NORMAL_FRAME:
{ {
RsApplication::refreshStyleSheet(this, false); Rshare::refreshStyleSheet(this, false);
break; break;
} }
case STATUS_FRAME: case STATUS_FRAME:
@ -252,7 +252,7 @@ void AvatarWidget::updateStatus(int status)
mPeerState = status; mPeerState = status;
setEnabled(((uint32_t) status == RS_STATUS_OFFLINE) ? false : true); setEnabled(((uint32_t) status == RS_STATUS_OFFLINE) ? false : true);
RsApplication::refreshStyleSheet(this, false); Rshare::refreshStyleSheet(this, false);
} }
void AvatarWidget::updateAvatar(const QString &peerId) void AvatarWidget::updateAvatar(const QString &peerId)

View File

@ -65,7 +65,7 @@ static const uint32_t NODE_DETAILS_UPDATE_DELAY = 5; // update each node every 5
RsFriendListModel::RsFriendListModel(QObject *parent) RsFriendListModel::RsFriendListModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
, mDisplayGroups(true), mDisplayStatusString(true), mDisplayStatusIcon (false) , mDisplayGroups(true), mDisplayStatusString(true)
, mLastInternalDataUpdate(0), mLastNodeUpdate(0) , mLastInternalDataUpdate(0), mLastNodeUpdate(0)
{ {
mFilterStrings.clear(); mFilterStrings.clear();
@ -141,39 +141,13 @@ template<> bool RsFriendListModel::convertInternalIdToIndex<8>(quintptr ref,Entr
return true; 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 RsFriendListModel::setDisplayStatusString(bool b) void RsFriendListModel::setDisplayStatusString(bool b)
{ {
preMods();
mDisplayStatusString = b; mDisplayStatusString = b;
postMods(); postMods();
} }
void RsFriendListModel::setDisplayStatusIcon(bool b)
{
preMods();
mDisplayStatusIcon = b;
postMods();
}
void RsFriendListModel::setDisplayGroups(bool b) void RsFriendListModel::setDisplayGroups(bool b)
{ {
mDisplayGroups = b; mDisplayGroups = b;
@ -313,7 +287,7 @@ uint32_t RsFriendListModel::EntryIndex::parentRow(uint32_t nb_groups) const
QModelIndex RsFriendListModel::index(int row, int column, const QModelIndex& parent) const QModelIndex RsFriendListModel::index(int row, int column, const QModelIndex& parent) const
{ {
if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent)) if(row < 0 || column < 0 || column >= COLUMN_THREAD_NB_COLUMNS)
return QModelIndex(); return QModelIndex();
if(parent.internalId() == 0) if(parent.internalId() == 0)
@ -440,27 +414,16 @@ QVariant RsFriendListModel::textColorRole(const EntryIndex& fmpe,int column) con
switch(fmpe.type) switch(fmpe.type)
{ {
case ENTRY_TYPE_GROUP: return QVariant(QBrush(mTextColorGroup)); case ENTRY_TYPE_GROUP: return QVariant(QBrush(mTextColorGroup));
case ENTRY_TYPE_PROFILE: return QVariant(QBrush(mTextColorStatus[onlineRole(fmpe,column).toInt()])); case ENTRY_TYPE_PROFILE:
case ENTRY_TYPE_NODE: return QVariant(QBrush(mTextColorStatus[statusRole(fmpe,column).toInt()])); case ENTRY_TYPE_NODE: return QVariant(QBrush(mTextColorStatus[onlineRole(fmpe,column).toInt()]));
default: default:
return QVariant(); return QVariant();
} }
} }
// statusRole returns the status (e.g. RS_STATUS_BUSY). It is used only to change the font color QVariant RsFriendListModel::statusRole(const EntryIndex& /*fmpe*/,int /*column*/) const
QVariant RsFriendListModel::statusRole(const EntryIndex& fmpe,int /*column*/) const
{ {
const HierarchicalNodeInformation *node = getNodeInfo(fmpe); return QVariant();//fmpe.mMsgStatus);
if(node)
{
StatusInfo status;
rsStatus->getStatus(node->node_info.id, status);
return QVariant(status.status);
}
return QVariant();
} }
bool RsFriendListModel::passesFilter(const EntryIndex& e,int /*column*/) const bool RsFriendListModel::passesFilter(const EntryIndex& e,int /*column*/) const
@ -585,9 +548,6 @@ QVariant RsFriendListModel::sortRole(const EntryIndex& entry,int column) const
} }
} }
// Only returns two values: RS_STATUS_ONLINE, or RS_STATUS_OFFLINE. This is used to decide on text font (bold)
// and whether profiles have children or not when offline nodes are shown.
QVariant RsFriendListModel::onlineRole(const EntryIndex& e, int /*col*/) const QVariant RsFriendListModel::onlineRole(const EntryIndex& e, int /*col*/) const
{ {
switch(e.type) switch(e.type)
@ -625,10 +585,13 @@ QVariant RsFriendListModel::onlineRole(const EntryIndex& e, int /*col*/) const
{ {
const HierarchicalNodeInformation *node = getNodeInfo(e); const HierarchicalNodeInformation *node = getNodeInfo(e);
if(node && bool(node->node_info.state & RS_PEER_STATE_CONNECTED)) if(node)
return QVariant(RS_STATUS_ONLINE); {
else StatusInfo status;
return QVariant(RS_STATUS_OFFLINE); rsStatus->getStatus(node->node_info.id, status);
return QVariant(status.status);
}
} }
} }
return QVariant(RS_STATUS_OFFLINE); return QVariant(RS_STATUS_OFFLINE);
@ -663,6 +626,12 @@ QVariant RsFriendListModel::fontRole(const EntryIndex& e, int col) const
} }
} }
class AutoEndel
{
public:
~AutoEndel() { std::cerr << std::endl;}
};
QVariant RsFriendListModel::displayRole(const EntryIndex& e, int col) const QVariant RsFriendListModel::displayRole(const EntryIndex& e, int col) const
{ {
#ifdef DEBUG_MODEL_INDEX #ifdef DEBUG_MODEL_INDEX
@ -781,7 +750,7 @@ QVariant RsFriendListModel::displayRole(const EntryIndex& e, int col) const
else else
{ {
return QVariant(QString::fromUtf8(node->node_info.location.c_str())+"\n" return QVariant(QString::fromUtf8(node->node_info.location.c_str())+"\n"
+ "(" + StatusDefs::name(statusRole(e,col).toInt()) + ")"); + "(" + StatusDefs::name(onlineRole(e,col).toInt()) + ")");
} }
else else
return QVariant(QString::fromUtf8(node->node_info.location.c_str())); return QVariant(QString::fromUtf8(node->node_info.location.c_str()));
@ -900,69 +869,6 @@ bool RsFriendListModel::getPeerOnlineStatus(const EntryIndex& e) const
return (noded && (noded->node_info.state & RS_PEER_STATE_CONNECTED)); return (noded && (noded->node_info.state & RS_PEER_STATE_CONNECTED));
} }
const RsFriendListModel::HierarchicalNodeInformation *RsFriendListModel::getBestNodeInformation(const HierarchicalProfileInformation *profileInfo, uint32_t *status) const
{
if (status) {
*status = RS_STATUS_OFFLINE;
}
if (!profileInfo) {
return NULL;
}
const RsFriendListModel::HierarchicalNodeInformation *bestNodeInformation = NULL;
int bestStatusIndex = 0;
/* Find the best status */
for (uint32_t i = 0; i < profileInfo->child_node_indices.size(); ++i) {
const RsFriendListModel::HierarchicalNodeInformation &nodeInformation = mLocations[profileInfo->child_node_indices[i]];
StatusInfo statusInfo;
rsStatus->getStatus(nodeInformation.node_info.id, statusInfo);
int statusIndex = 0;
switch (statusInfo.status) {
case RS_STATUS_OFFLINE:
statusIndex = 1;
break;
case RS_STATUS_INACTIVE:
statusIndex = 2;
break;
case RS_STATUS_AWAY:
statusIndex = 3;
break;
case RS_STATUS_BUSY:
statusIndex = 4;
break;
case RS_STATUS_ONLINE:
statusIndex = 5;
break;
default:
std::cerr << "FriendListModel: Unknown status " << statusInfo.status << std::endl;
}
if (bestStatusIndex == 0 || statusIndex > bestStatusIndex) {
/* first status or better status */
bestStatusIndex = statusIndex;
bestNodeInformation = &nodeInformation;
if (status) {
*status = statusInfo.status;
}
}
}
if (bestStatusIndex == 0) {
return NULL;
}
return bestNodeInformation;
}
QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) const QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) const
{ {
if(col > 0) if(col > 0)
@ -996,42 +902,13 @@ QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) cons
{ {
if(!isProfileExpanded(entry)) if(!isProfileExpanded(entry))
{ {
QPixmap sslAvatar; QPixmap sslAvatar = FilesDefs::getPixmapFromQtResourcePath(AVATAR_DEFAULT_IMAGE);
bool foundAvatar = false;
const HierarchicalProfileInformation *hn = getProfileInfo(entry); const HierarchicalProfileInformation *hn = getProfileInfo(entry);
uint32_t status = RS_STATUS_OFFLINE;
const HierarchicalNodeInformation *bestNodeInformation = NULL;
if (mDisplayStatusIcon) { for(uint32_t i=0;i<hn->child_node_indices.size();++i)
bestNodeInformation = getBestNodeInformation(hn, &status); if(AvatarDefs::getAvatarFromSslId(RsPeerId(mLocations[hn->child_node_indices[i]].node_info.id.toStdString()), sslAvatar))
if (bestNodeInformation) { return QVariant(QIcon(sslAvatar));
if (AvatarDefs::getAvatarFromSslId(RsPeerId(bestNodeInformation->node_info.id.toStdString()), sslAvatar, "")) {
/* Use avatar from best node */
foundAvatar = true;
}
}
}
if (!foundAvatar) {
/* Use first available avatar */
for(uint32_t i=0;i<hn->child_node_indices.size();++i) {
if(AvatarDefs::getAvatarFromSslId(RsPeerId(mLocations[hn->child_node_indices[i]].node_info.id.toStdString()), sslAvatar, "")) {
foundAvatar = true;
break;
}
}
}
if (!foundAvatar || sslAvatar.isNull()) {
sslAvatar = FilesDefs::getPixmapFromQtResourcePath(AVATAR_DEFAULT_IMAGE);
}
if (mDisplayStatusIcon) {
if (bestNodeInformation) {
QPixmap sslOverlayIcon = FilesDefs::getPixmapFromQtResourcePath(StatusDefs::imageStatus(status));
return QVariant(QIcon(createAvatar(sslAvatar, sslOverlayIcon)));
}
}
return QVariant(QIcon(sslAvatar)); return QVariant(QIcon(sslAvatar));
} }
@ -1048,10 +925,6 @@ QVariant RsFriendListModel::decorationRole(const EntryIndex& entry,int col) cons
QPixmap sslAvatar; QPixmap sslAvatar;
AvatarDefs::getAvatarFromSslId(RsPeerId(hn->node_info.id.toStdString()), sslAvatar); AvatarDefs::getAvatarFromSslId(RsPeerId(hn->node_info.id.toStdString()), sslAvatar);
if (mDisplayStatusIcon) {
QPixmap sslOverlayIcon = FilesDefs::getPixmapFromQtResourcePath(StatusDefs::imageStatus(statusRole(entry, col).toInt()));
return QVariant(QIcon(createAvatar(sslAvatar, sslOverlayIcon)));
}
return QVariant(QIcon(sslAvatar)); return QVariant(QIcon(sslAvatar));
} }

View File

@ -129,10 +129,6 @@ public:
void setDisplayStatusString(bool b); void setDisplayStatusString(bool b);
bool getDisplayStatusString() const { return mDisplayStatusString; } bool getDisplayStatusString() const { return mDisplayStatusString; }
void setDisplayStatusIcon(bool b);
bool getDisplayStatusIcon() const { return mDisplayStatusIcon; }
EntryType getType(const QModelIndex&) const; EntryType getType(const QModelIndex&) const;
@ -223,14 +219,11 @@ private:
uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings); uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings);
const HierarchicalNodeInformation *getBestNodeInformation(const HierarchicalProfileInformation *profileInfo, uint32_t *status = NULL) const;
QStringList mFilterStrings; QStringList mFilterStrings;
FilterType mFilterType; FilterType mFilterType;
bool mDisplayGroups ; bool mDisplayGroups ;
bool mDisplayStatusString ; bool mDisplayStatusString ;
bool mDisplayStatusIcon ;
rstime_t mLastInternalDataUpdate; rstime_t mLastInternalDataUpdate;
rstime_t mLastNodeUpdate;; rstime_t mLastNodeUpdate;;

View File

@ -127,7 +127,7 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent)
ui->filterLineEdit->showFilterIcon(); ui->filterLineEdit->showFilterIcon();
/* Refresh style to have the correct text color */ /* Refresh style to have the correct text color */
RsApplication::refreshStyleSheet(this, false); Rshare::refreshStyleSheet(this, false);
mEventHandlerId_identities = 0; mEventHandlerId_identities = 0;
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) {
@ -135,8 +135,6 @@ FriendSelectionWidget::FriendSelectionWidget(QWidget *parent)
mEventHandlerId_peers = 0; mEventHandlerId_peers = 0;
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) {
RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }) ;}, mEventHandlerId_peers, RsEventType::PEER_CONNECTION ); 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<const RsEvent> event) void FriendSelectionWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
@ -1227,7 +1225,7 @@ std::string FriendSelectionWidget::idFromItem(QTreeWidgetItem *item)
return item->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); return item->data(COLUMN_DATA, ROLE_ID).toString().toStdString();
} }
void FriendSelectionWidget::sortByChecked(bool) void FriendSelectionWidget::sortByChecked(bool sort)
{ {
mCompareRole->clear(); mCompareRole->clear();
mCompareRole->setRole(COLUMN_NAME,ROLE_SORT_SELECTED); mCompareRole->setRole(COLUMN_NAME,ROLE_SORT_SELECTED);

View File

@ -26,7 +26,6 @@
#include "retroshare/rsevents.h" #include "retroshare/rsevents.h"
#include <gui/gxs/RsGxsUpdateBroadcastPage.h> #include <gui/gxs/RsGxsUpdateBroadcastPage.h>
#include "util/FontSizeHandler.h"
namespace Ui { namespace Ui {
class FriendSelectionWidget; class FriendSelectionWidget;
@ -179,8 +178,6 @@ private:
std::set<std::string> 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. std::set<std::string> 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_identities;
RsEventsHandlerId_t mEventHandlerId_peers; RsEventsHandlerId_t mEventHandlerId_peers;
}; };

View File

@ -38,6 +38,11 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>
@ -66,7 +71,7 @@
<customwidget> <customwidget>
<class>LineEditClear</class> <class>LineEditClear</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header>gui/common/LineEditClear.h</header> <header location="global">gui/common/LineEditClear.h</header>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>RSTreeWidget</class> <class>RSTreeWidget</class>

View File

@ -148,19 +148,7 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) :
connect(ui->distantSearchLineEdit,SIGNAL(returnPressed()),this,SLOT(distantSearch())) ; connect(ui->distantSearchLineEdit,SIGNAL(returnPressed()),this,SLOT(distantSearch())) ;
mFontSizeHandler.registerFontSize(ui->treeWidget, 1.8f, [this] (QAbstractItemView*, int fontSize) { ui->treeWidget->setIconSize(QSize(H*1.8,H*1.8));
// 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() GroupTreeWidget::~GroupTreeWidget()
@ -266,8 +254,8 @@ QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIc
RSTreeWidgetItem *item = new RSTreeWidgetItem(); RSTreeWidgetItem *item = new RSTreeWidgetItem();
ui->treeWidget->addTopLevelItem(item); ui->treeWidget->addTopLevelItem(item);
// To get StyleSheet for Items // To get StyleSheet for Items
// ui->treeWidget->style()->unpolish(ui->treeWidget); ui->treeWidget->style()->unpolish(ui->treeWidget);
// ui->treeWidget->style()->polish(ui->treeWidget); ui->treeWidget->style()->polish(ui->treeWidget);
item->setText(GTW_COLUMN_NAME, name); item->setText(GTW_COLUMN_NAME, name);
item->setData(GTW_COLUMN_DATA, ROLE_NAME, name); item->setData(GTW_COLUMN_DATA, ROLE_NAME, name);
@ -402,7 +390,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
if (item == NULL) { if (item == NULL) {
item = new RSTreeWidgetItem(compareRole); item = new RSTreeWidgetItem(compareRole);
item->setData(GTW_COLUMN_DATA, ROLE_ID, itemInfo.id); item->setData(GTW_COLUMN_DATA, ROLE_ID, itemInfo.id);
item->setFont(GTW_COLUMN_NAME, ui->treeWidget->font()); item->setFont(GTW_COLUMN_DATA, ui->treeWidget->font());
//static_cast<RSTreeWidgetItem*>(item)->setNoDataAsLast(true); //Uncomment this to sort data with QVariant() always at end. //static_cast<RSTreeWidgetItem*>(item)->setNoDataAsLast(true); //Uncomment this to sort data with QVariant() always at end.
categoryItem->addChild(item); categoryItem->addChild(item);
} }

View File

@ -25,7 +25,6 @@
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include <QDateTime> #include <QDateTime>
#include "util/FontSizeHandler.h"
class QToolButton; class QToolButton;
class RshareSettings; class RshareSettings;
@ -164,7 +163,6 @@ private:
// Compare role used for each column // Compare role used for each column
RSTreeWidgetItemCompareRole *compareRole; RSTreeWidgetItemCompareRole *compareRole;
FontSizeHandler mFontSizeHandler;
Ui::GroupTreeWidget *ui; Ui::GroupTreeWidget *ui;
}; };

View File

@ -35,10 +35,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin"> <property name="leftMargin">
@ -70,6 +70,11 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>

View File

@ -234,10 +234,8 @@ void LineEditClear::setFilterButtonIcon(const QIcon &icon)
mFilterButton->setIcon(icon); mFilterButton->setIcon(icon);
ensurePolished(); ensurePolished();
#if !defined(Q_OS_DARWIN)
QFontMetrics fm(this->font()); QFontMetrics fm(this->font());
QSize size(fm.width("___"), fm.height()); QSize size(fm.width("___"), fm.height());
mFilterButton->setFixedSize(size); mFilterButton->setFixedSize(size);
mFilterButton->setIconSize(size); mFilterButton->setIconSize(size);
#endif
} }

View File

@ -1,27 +0,0 @@
// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef MACDOCKICONHANDLER_H
#define MACDOCKICONHANDLER_H
#include <QObject>
/** macOS-specific Dock icon handler.
*/
class MacDockIconHandler : public QObject
{
Q_OBJECT
public:
static MacDockIconHandler *instance();
static void cleanup();
Q_SIGNALS:
void dockIconClicked();
private:
MacDockIconHandler();
};
#endif // MACDOCKICONHANDLER_H

View File

@ -1,53 +0,0 @@
// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "MacDockIconHandler.h"
#include <AppKit/AppKit.h>
#include <objc/runtime.h>
static MacDockIconHandler *s_instance = nullptr;
bool dockClickHandler(id self, SEL _cmd, ...) {
Q_UNUSED(self)
Q_UNUSED(_cmd)
Q_EMIT s_instance->dockIconClicked();
// Return NO (false) to suppress the default macOS actions
return false;
}
void setupDockClickHandler() {
Class delClass = (Class)[[[NSApplication sharedApplication] delegate] class];
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
}
MacDockIconHandler::MacDockIconHandler() : QObject()
{
setupDockClickHandler();
}
MacDockIconHandler *MacDockIconHandler::instance()
{
if (!s_instance)
s_instance = new MacDockIconHandler();
return s_instance;
}
void MacDockIconHandler::cleanup()
{
delete s_instance;
}
/**
* Force application activation on macOS. With Qt 5.5.1 this is required when
* an action in the Dock menu is triggered.
* TODO: Define a Qt version where it's no-longer necessary.
*/
void ForceActivation()
{
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}

View File

@ -54,7 +54,6 @@
#include "gui/chat/ChatUserNotify.h" #include "gui/chat/ChatUserNotify.h"
#include "gui/connect/ConnectProgressDialog.h" #include "gui/connect/ConnectProgressDialog.h"
#include "gui/common/ElidedLabel.h" #include "gui/common/ElidedLabel.h"
#include "gui/notifyqt.h"
#include "NewFriendList.h" #include "NewFriendList.h"
#include "ui_NewFriendList.h" #include "ui_NewFriendList.h"
@ -203,9 +202,6 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId_peer, RsEventType::PEER_CONNECTION ); rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId_peer, RsEventType::PEER_CONNECTION );
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId_gssp, RsEventType::GOSSIP_DISCOVERY ); rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> e) { handleEvent(e); }, mEventHandlerId_gssp, RsEventType::GOSSIP_DISCOVERY );
connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(QString)), this, SLOT(forceUpdateDisplay()));
connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(QString,int)), this, SLOT(forceUpdateDisplay()));
mModel = new RsFriendListModel(ui->peerTreeWidget); mModel = new RsFriendListModel(ui->peerTreeWidget);
mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this); mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this);
@ -265,7 +261,6 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par
connect(ui->actionShowOfflineFriends, SIGNAL(triggered(bool)), this, SLOT(setShowUnconnected(bool))); connect(ui->actionShowOfflineFriends, SIGNAL(triggered(bool)), this, SLOT(setShowUnconnected(bool)));
connect(ui->actionShowState, SIGNAL(triggered(bool)), this, SLOT(setShowState(bool)) ); connect(ui->actionShowState, SIGNAL(triggered(bool)), this, SLOT(setShowState(bool)) );
connect(ui->actionShowStateIcon, SIGNAL(triggered(bool)), this, SLOT(setShowStateIcon(bool)) );
connect(ui->actionShowGroups, SIGNAL(triggered(bool)), this, SLOT(setShowGroups(bool)) ); connect(ui->actionShowGroups, SIGNAL(triggered(bool)), this, SLOT(setShowGroups(bool)) );
connect(ui->actionExportFriendlist, SIGNAL(triggered()) , this, SLOT(exportFriendlistClicked())); connect(ui->actionExportFriendlist, SIGNAL(triggered()) , this, SLOT(exportFriendlistClicked()));
connect(ui->actionImportFriendlist, SIGNAL(triggered()) , this, SLOT(importFriendlistClicked())); connect(ui->actionImportFriendlist, SIGNAL(triggered()) , this, SLOT(importFriendlistClicked()));
@ -273,8 +268,6 @@ NewFriendList::NewFriendList(QWidget */*parent*/) : /* RsAutoUpdatePage(5000,par
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)),Qt::QueuedConnection); connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)),Qt::QueuedConnection);
connect(h, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint))); connect(h, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint)));
mFontSizeHandler.registerFontSize(ui->peerTreeWidget,1.5f);
// #ifdef RS_DIRECT_CHAT // #ifdef RS_DIRECT_CHAT
// connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatNode())); // connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatNode()));
// #endif // #endif
@ -348,12 +341,10 @@ void NewFriendList::headerContextMenuRequested(QPoint /*p*/)
displayMenu.addAction(ui->actionShowOfflineFriends); displayMenu.addAction(ui->actionShowOfflineFriends);
displayMenu.addAction(ui->actionShowState); displayMenu.addAction(ui->actionShowState);
displayMenu.addAction(ui->actionShowStateIcon);
displayMenu.addAction(ui->actionShowGroups); displayMenu.addAction(ui->actionShowGroups);
ui->actionShowOfflineFriends->setChecked(mProxyModel->showOfflineNodes()); ui->actionShowOfflineFriends->setChecked(mProxyModel->showOfflineNodes());
ui->actionShowState->setChecked(mModel->getDisplayStatusString()); ui->actionShowState->setChecked(mModel->getDisplayStatusString());
ui->actionShowStateIcon->setChecked(mModel->getDisplayStatusIcon());
ui->actionShowGroups->setChecked(mModel->getDisplayGroups()); ui->actionShowGroups->setChecked(mModel->getDisplayGroups());
QHeaderView *header = ui->peerTreeWidget->header(); QHeaderView *header = ui->peerTreeWidget->header();
@ -514,8 +505,6 @@ void NewFriendList::processSettings(bool load)
mModel->setDisplayStatusString(Settings->value("showState", mModel->getDisplayStatusString()).toBool()); mModel->setDisplayStatusString(Settings->value("showState", mModel->getDisplayStatusString()).toBool());
mModel->setDisplayGroups(Settings->value("showGroups", mModel->getDisplayGroups()).toBool()); mModel->setDisplayGroups(Settings->value("showGroups", mModel->getDisplayGroups()).toBool());
mModel->setDisplayStatusIcon(Settings->value("showStateIcon", mModel->getDisplayStatusIcon()).toBool());
setColumnVisible(RsFriendListModel::COLUMN_THREAD_IP,Settings->value("showIP", isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP)).toBool()); setColumnVisible(RsFriendListModel::COLUMN_THREAD_IP,Settings->value("showIP", isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP)).toBool());
setColumnVisible(RsFriendListModel::COLUMN_THREAD_ID,Settings->value("showID", isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID)).toBool()); setColumnVisible(RsFriendListModel::COLUMN_THREAD_ID,Settings->value("showID", isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID)).toBool());
@ -539,8 +528,6 @@ void NewFriendList::processSettings(bool load)
Settings->setValue("hideUnconnected", !mProxyModel->showOfflineNodes()); Settings->setValue("hideUnconnected", !mProxyModel->showOfflineNodes());
Settings->setValue("showState", mModel->getDisplayStatusString()); Settings->setValue("showState", mModel->getDisplayStatusString());
Settings->setValue("showGroups", mModel->getDisplayGroups()); Settings->setValue("showGroups", mModel->getDisplayGroups());
Settings->setValue("showStateIcon", mModel->getDisplayStatusIcon());
Settings->setValue("showIP",isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP)); Settings->setValue("showIP",isColumnVisible(RsFriendListModel::COLUMN_THREAD_IP));
Settings->setValue("showID",isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID)); Settings->setValue("showID",isColumnVisible(RsFriendListModel::COLUMN_THREAD_ID));
@ -1656,12 +1643,6 @@ void NewFriendList::setShowState(bool show)
processSettings(false); processSettings(false);
} }
void NewFriendList::setShowStateIcon(bool show)
{
applyWhileKeepingTree([show,this]() { mModel->setDisplayStatusIcon(show) ; });
processSettings(false);
}
void NewFriendList::setShowGroups(bool show) void NewFriendList::setShowGroups(bool show)
{ {
applyWhileKeepingTree([show,this]() { mModel->setDisplayGroups(show) ; }); applyWhileKeepingTree([show,this]() { mModel->setDisplayGroups(show) ; });

View File

@ -29,7 +29,6 @@
#include "FriendListModel.h" #include "FriendListModel.h"
#include "retroshare/rsstatus.h" #include "retroshare/rsstatus.h"
#include "util/FontSizeHandler.h"
namespace Ui { namespace Ui {
class NewFriendList; class NewFriendList;
@ -88,9 +87,7 @@ public slots:
void setShowGroups(bool show); void setShowGroups(bool show);
void setShowUnconnected(bool hidden); void setShowUnconnected(bool hidden);
void setShowState(bool show); void setShowState(bool show);
void setShowStateIcon(bool show);
void headerContextMenuRequested(QPoint); void headerContextMenuRequested(QPoint);
void exportFriendlistClicked();
private slots: private slots:
void sortColumn(int col,Qt::SortOrder so); void sortColumn(int col,Qt::SortOrder so);
@ -105,7 +102,6 @@ private:
Ui::NewFriendList *ui; Ui::NewFriendList *ui;
RsFriendListModel *mModel; RsFriendListModel *mModel;
QAction *mActionSortByState; QAction *mActionSortByState;
FontSizeHandler mFontSizeHandler;
void applyWhileKeepingTree(std::function<void()> predicate); void applyWhileKeepingTree(std::function<void()> predicate);
@ -168,5 +164,6 @@ private slots:
void editGroup(); void editGroup();
void removeGroup(); void removeGroup();
void exportFriendlistClicked();
void importFriendlistClicked(); void importFriendlistClicked();
}; };

View File

@ -29,10 +29,10 @@
<item> <item>
<widget class="QFrame" name="toolBarFrame"> <widget class="QFrame" name="toolBarFrame">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="toolBarFrame_HL"> <layout class="QHBoxLayout" name="toolBarFrame_HL">
<property name="spacing"> <property name="spacing">
@ -58,6 +58,11 @@
</item> </item>
<item> <item>
<widget class="QTreeView" name="peerTreeWidget"> <widget class="QTreeView" name="peerTreeWidget">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>
@ -119,17 +124,6 @@
<string>import your friendlist including groups</string> <string>import your friendlist including groups</string>
</property> </property>
</action> </action>
<action name="actionShowStateIcon">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Status icons</string>
</property>
<property name="toolTip">
<string>Show status icons</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -37,21 +37,28 @@
const QString RsCollection::ExtensionString = QString("rscollection") ; const QString RsCollection::ExtensionString = QString("rscollection") ;
RsCollection::RsCollection() RsCollection::RsCollection(QObject *parent)
: QObject(parent), _xml_doc("RsCollection")
{ {
mFileTree = std::unique_ptr<RsFileTree>(new RsFileTree()); _root = _xml_doc.createElement("RsCollection");
} _xml_doc.appendChild(_root);
RsCollection::RsCollection(const RsFileTree& ft)
{
mFileTree = std::unique_ptr<RsFileTree>(new RsFileTree(ft));
for(uint64_t i=0;i<mFileTree->numFiles();++i)
mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i ));
} }
RsCollection::RsCollection(const std::vector<DirDetails>& file_infos,FileSearchFlags flags) RsCollection::RsCollection(const RsFileTree& fr)
: mFileTree(new RsFileTree) : _xml_doc("RsCollection")
{ {
_root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(_root);
recursAddElements(_xml_doc,fr,0,_root) ;
}
RsCollection::RsCollection(const std::vector<DirDetails>& file_infos,FileSearchFlags flags, QObject *parent)
: QObject(parent), _xml_doc("RsCollection")
{
_root = _xml_doc.createElement("RsCollection");
_xml_doc.appendChild(_root);
if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE))) if(! ( (flags & RS_FILE_HINTS_LOCAL) || (flags & RS_FILE_HINTS_REMOTE)))
{ {
std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl; std::cerr << "(EE) Wrong flags passed to RsCollection constructor. Please fix the code!" << std::endl;
@ -59,16 +66,42 @@ RsCollection::RsCollection(const std::vector<DirDetails>& file_infos,FileSearchF
} }
for(uint32_t i = 0;i<file_infos.size();++i) for(uint32_t i = 0;i<file_infos.size();++i)
recursAddElements(mFileTree->root(),file_infos[i],flags) ; recursAddElements(_xml_doc,file_infos[i],_root,flags) ;
for(uint64_t i=0;i<mFileTree->numFiles();++i)
mHashes.insert(std::make_pair(mFileTree->fileData(i).hash,i ));
} }
RsCollection::~RsCollection() RsCollection::~RsCollection()
{ {
} }
void RsCollection::downloadFiles() const
{
// print out the element names of all elements that are direct children
// of the outermost element.
QDomElement docElem = _xml_doc.documentElement();
std::vector<ColFileInfo> colFileInfos ;
recursCollectColFileInfos(docElem,colFileInfos,QString(),false) ;
RsCollectionDialog(_fileName, colFileInfos, false).exec() ;
}
void RsCollection::autoDownloadFiles() const
{
QDomElement docElem = _xml_doc.documentElement();
std::vector<ColFileInfo> colFileInfos;
recursCollectColFileInfos(docElem,colFileInfos,QString(),false);
QString dlDir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str());
foreach(ColFileInfo colFileInfo, colFileInfos)
{
autoDownloadFiles(colFileInfo, dlDir);
}
}
void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const void RsCollection::autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const
{ {
if (!colFileInfo.filename_has_wrong_characters) if (!colFileInfo.filename_has_wrong_characters)
@ -110,126 +143,210 @@ static QString purifyFileName(const QString& input,bool& bad)
return output ; return output ;
} }
void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index) void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash)
{ {
mHashes[hash]= mFileTree->addFile(parent_index,fname.toStdString(),hash,size); ColFileInfo info ;
info.type = DIR_TYPE_FILE ;
info.name = fname ;
info.size = size ;
info.hash = QString::fromStdString(hash.toStdString()) ;
recursAddElements(_xml_doc,info,_root) ;
} }
void RsCollection::merge_in(const RsFileTree& tree, RsFileTree::DirIndex parent_index) void RsCollection::merge_in(const RsFileTree& tree)
{ {
recursMergeTree(mFileTree->root(),tree,tree.directoryData(parent_index)) ; recursAddElements(_xml_doc,tree,0,_root) ;
} }
void RsCollection::recursMergeTree(RsFileTree::DirIndex parent,const RsFileTree& tree,const RsFileTree::DirData& dd) void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector<ColFileInfo>& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const
{ {
for(uint32_t i=0;i<dd.subfiles.size();++i) QDomNode n = e.firstChild() ;
#ifdef COLLECTION_DEBUG
std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl;
#endif
while(!n.isNull())
{ {
const RsFileTree::FileData& fd(tree.fileData(dd.subfiles[i])); QDomElement ee = n.toElement(); // try to convert the node to an element.
mHashes[fd.hash] = mFileTree->addFile(parent,fd.name,fd.hash,fd.size);
#ifdef COLLECTION_DEBUG
std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl;
#endif
if(ee.tagName() == QString("File"))
{
ColFileInfo newChild ;
newChild.hash = ee.attribute(QString("sha1")) ;
bool bad_chars_detected = false ;
newChild.name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected) ;
newChild.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ;
newChild.size = ee.attribute(QString("size")).toULongLong() ;
newChild.path = current_path ;
newChild.type = DIR_TYPE_FILE ;
colFileInfos.push_back(newChild) ;
} }
for(uint32_t i=0;i<dd.subdirs.size();++i) else if(ee.tagName() == QString("Directory"))
{ {
const RsFileTree::DirData& ld(tree.directoryData(dd.subdirs[i])); ColFileInfo newParent ;
bool bad_chars_detected = false ;
QString cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected) ;
newParent.name=cleanDirName;
newParent.filename_has_wrong_characters = bad_chars_detected || bad_chars_in_parent ;
newParent.size = 0;
newParent.path = current_path ;
newParent.type = DIR_TYPE_DIR ;
auto new_dir_index = mFileTree->addDirectory(parent,ld.name); recursCollectColFileInfos(ee,newParent.children,current_path + "/" + cleanDirName, bad_chars_in_parent || bad_chars_detected) ;
recursMergeTree(new_dir_index,tree,ld); uint32_t size = newParent.children.size();
for(uint32_t i=0;i<size;++i)
{
const ColFileInfo &colFileInfo = newParent.children[i];
newParent.size +=colFileInfo.size ;
}
colFileInfos.push_back(newParent) ;
}
n = n.nextSibling() ;
} }
} }
void RsCollection::recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags)
{
if (dd.type == DIR_TYPE_FILE)
mHashes[dd.hash] = mFileTree->addFile(parent,dd.name,dd.hash,dd.size);
else if (dd.type == DIR_TYPE_DIR)
{
RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,dd.name);
for(uint32_t i=0;i<dd.children.size();++i) void RsCollection::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e,FileSearchFlags flags) const
{
if (details.type == DIR_TYPE_FILE)
{ {
if (!dd.children[i].ref) QDomElement f = doc.createElement("File") ;
f.setAttribute(QString("name"),QString::fromUtf8(details.name.c_str())) ;
f.setAttribute(QString("sha1"),QString::fromStdString(details.hash.toStdString())) ;
f.setAttribute(QString("size"),QString::number(details.size)) ;
e.appendChild(f) ;
}
else if (details.type == DIR_TYPE_DIR)
{
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),QString::fromUtf8(details.name.c_str())) ;
for(uint32_t i=0;i<details.children.size();++i)
{
if (!details.children[i].ref)
continue; continue;
DirDetails subDirDetails; DirDetails subDirDetails;
if (!rsFiles->RequestDirDetails(dd.children[i].ref, subDirDetails, flags)) if (!rsFiles->RequestDirDetails(details.children[i].ref, subDirDetails, flags))
continue; continue;
recursAddElements(new_dir_index,subDirDetails,flags) ; recursAddElements(doc,subDirDetails,d,flags) ;
} }
e.appendChild(d) ;
} }
} }
QString RsCollection::errorString(RsCollectionErrorCode code) void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const
{ {
switch(code) if (colFileInfo.type == DIR_TYPE_FILE)
{ {
default: [[fallthrough]] ; QDomElement f = doc.createElement("File") ;
case RsCollectionErrorCode::UNKNOWN_ERROR: return QObject::tr("Unknown error");
case RsCollectionErrorCode::COLLECTION_NO_ERROR: return QObject::tr("No error"); f.setAttribute(QString("name"),colFileInfo.name) ;
case RsCollectionErrorCode::FILE_READ_ERROR: return QObject::tr("Error while openning file"); f.setAttribute(QString("sha1"),colFileInfo.hash) ;
case RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS: return QObject::tr("Collection file contains potentially harmful code"); f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ;
case RsCollectionErrorCode::INVALID_ROOT_NODE: return QObject::tr("Invalid root node. RsCollection node was expected.");
case RsCollectionErrorCode::XML_PARSING_ERROR: return QObject::tr("XML parsing error in collection file"); e.appendChild(f) ;
}
else if (colFileInfo.type == DIR_TYPE_DIR)
{
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),colFileInfo.name) ;
for (std::vector<ColFileInfo>::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it)
recursAddElements(doc,(*it),d) ;
e.appendChild(d) ;
} }
} }
RsCollection::RsCollection(const RsCollection& col) void RsCollection::recursAddElements(
: mFileTree(new RsFileTree(*col.mFileTree)),mHashes(col.mHashes) QDomDocument& doc, const RsFileTree& ft, uint32_t index,
QDomElement& e ) const
{ {
std::vector<uint64_t> subdirs;
std::vector<RsFileTree::FileData> subfiles ;
std::string name;
if(!ft.getDirectoryContent(name, subdirs, subfiles, index)) return;
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ;
e.appendChild(d) ;
for (uint32_t i=0;i<subdirs.size();++i)
recursAddElements(doc,ft,subdirs[i],d) ;
for(uint32_t i=0;i<subfiles.size();++i)
{
QDomElement f = doc.createElement("File") ;
f.setAttribute(QString("name"),QString::fromUtf8(subfiles[i].name.c_str())) ;
f.setAttribute(QString("sha1"),QString::fromStdString(subfiles[i].hash.toStdString())) ;
f.setAttribute(QString("size"),QString::number(subfiles[i].size)) ;
d.appendChild(f) ;
}
} }
RsCollection::RsCollection(const QString& fileName, RsCollectionErrorCode& error) static void showErrorBox(const QString& fileName, const QString& error)
: mFileTree(new RsFileTree)
{ {
if (!checkFile(fileName,error)) QMessageBox mb(QMessageBox::Warning, QObject::tr("Failed to process collection file"), QObject::tr("The collection file %1 could not be opened.\nReported error is: \n\n%2").arg(fileName).arg(error), QMessageBox::Ok);
return ; mb.exec();
}
bool RsCollection::load(const QString& fileName, bool showError /* = true*/)
{
if (!checkFile(fileName,showError)) return false;
QFile file(fileName); QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
{ {
std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl;
error = RsCollectionErrorCode::FILE_READ_ERROR; if (showError) {
//showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName)); showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName));
return ; }
return false;
} }
QDomDocument xml_doc; bool ok = _xml_doc.setContent(&file) ;
bool ok = xml_doc.setContent(&file) ;
if(!ok)
{
error = RsCollectionErrorCode::XML_PARSING_ERROR;
return;
}
file.close(); file.close();
QDomNode root = xml_doc.elementsByTagName("RsCollection").at(0).toElement(); if (ok) {
_fileName = fileName;
if(root.isNull()) } else {
{ if (showError) {
error = RsCollectionErrorCode::INVALID_ROOT_NODE; showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Error parsing xml file"));
return; }
} }
if(!recursParseXml(xml_doc,root,0)) return ok;
error = RsCollectionErrorCode::XML_PARSING_ERROR;
else
error = RsCollectionErrorCode::COLLECTION_NO_ERROR;
} }
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this // check that the file is a valid rscollection file, and not a lol bomb or some shit like this
bool RsCollection::checkFile(const QString& fileName, bool showError)
bool RsCollection::checkFile(const QString& fileName, RsCollectionErrorCode& error)
{ {
QFile file(fileName); QFile file(fileName);
error = RsCollectionErrorCode::COLLECTION_NO_ERROR;
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
{ {
std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl; std::cerr << "Cannot open file " << fileName.toStdString() << " !!" << std::endl;
error = RsCollectionErrorCode::FILE_READ_ERROR; if (showError) {
showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName));
//showErrorBox(fileName, QApplication::translate("RsCollectionFile", "Cannot open file %1").arg(fileName)); }
return false; return false;
} }
if (file.reset()){ if (file.reset()){
@ -271,8 +388,7 @@ bool RsCollection::checkFile(const QString& fileName, RsCollectionErrorCode& err
for(uint i=0;i<bad_strings.size();++i) for(uint i=0;i<bad_strings.size();++i)
if(std::string(current,bad_strings[i].length()) == bad_strings[i]) if(std::string(current,bad_strings[i].length()) == bad_strings[i])
{ {
//showErrorBox(file.fileName(), QApplication::translate("RsCollectionFile", "This file contains the string \"%1\" and is therefore an invalid collection file. \n\nIf you believe it is correct, remove the corresponding line from the file and re-open it with Retroshare.").arg(bad_strings[i].c_str())); showErrorBox(file.fileName(), QApplication::translate("RsCollectionFile", "This file contains the string \"%1\" and is therefore an invalid collection file. \n\nIf you believe it is correct, remove the corresponding line from the file and re-open it with Retroshare.").arg(bad_strings[i].c_str()));
error = RsCollectionErrorCode::FILE_CONTAINS_HARMFUL_STRINGS;
file.close(); file.close();
return false ; return false ;
//std::cerr << "Bad string detected" << std::endl; //std::cerr << "Bad string detected" << std::endl;
@ -286,9 +402,18 @@ bool RsCollection::checkFile(const QString& fileName, RsCollectionErrorCode& err
file.close(); file.close();
return true; return true;
} }
error = RsCollectionErrorCode::UNKNOWN_ERROR;
return false; return false;
} }
bool RsCollection::load(QWidget *parent)
{
QString fileName;
if (!misc::getOpenFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
return false;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
return load(fileName, true);
}
bool RsCollection::save(const QString& fileName) const bool RsCollection::save(const QString& fileName) const
{ {
@ -300,103 +425,129 @@ bool RsCollection::save(const QString& fileName) const
return false; return false;
} }
QDomDocument xml_doc ;
QDomElement root = xml_doc.createElement("RsCollection");
const RsFileTree::DirData& root_data(mFileTree->directoryData(mFileTree->root()));
if(!recursExportToXml(xml_doc,root,root_data))
return false;
xml_doc.appendChild(root);
QTextStream stream(&file) ; QTextStream stream(&file) ;
stream.setCodec("UTF-8") ; stream.setCodec("UTF-8") ;
stream << xml_doc.toString() ; stream << _xml_doc.toString() ;
file.close(); file.close();
return true; return true;
} }
bool RsCollection::recursParseXml(QDomDocument& doc,const QDomNode& e,const RsFileTree::DirIndex parent) bool RsCollection::save(QWidget *parent) const
{ {
mHashes.clear(); QString fileName;
QDomNode n = e.firstChild() ; if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
#ifdef COLLECTION_DEBUG
std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl;
#endif
while(!n.isNull())
{
QDomElement ee = n.toElement(); // try to convert the node to an element.
#ifdef COLLECTION_DEBUG
std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl;
#endif
if(ee.tagName() == QString("File"))
{
RsFileHash hash(ee.attribute(QString("sha1")).toStdString()) ;
bool bad_chars_detected = false;
std::string name = purifyFileName(ee.attribute(QString("name")), bad_chars_detected).toUtf8().constData() ;
uint64_t size = ee.attribute(QString("size")).toULongLong() ;
mHashes[hash] = mFileTree->addFile(parent,name,hash,size);
}
else if(ee.tagName() == QString("Directory"))
{
bool bad_chars_detected = false ;
std::string cleanDirName = purifyFileName(ee.attribute(QString("name")),bad_chars_detected).toUtf8().constData() ;
RsFileTree::DirIndex new_dir_index = mFileTree->addDirectory(parent,cleanDirName);
recursParseXml(doc,ee,new_dir_index);
}
n = n.nextSibling() ;
}
return true;
}
bool RsCollection::recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const
{
for(uint32_t i=0;i<dd.subfiles.size();++i)
{
QDomElement f = doc.createElement("File") ;
const RsFileTree::FileData& fd(mFileTree->fileData(dd.subfiles[i]));
f.setAttribute(QString("name"),QString::fromUtf8(fd.name.c_str())) ;
f.setAttribute(QString("sha1"),QString::fromStdString(fd.hash.toStdString())) ;
f.setAttribute(QString("size"),QString::number(fd.size)) ;
e.appendChild(f) ;
}
for(uint32_t i=0;i<dd.subdirs.size();++i)
{
const RsFileTree::DirData& di(mFileTree->directoryData(dd.subdirs[i]));
QDomElement d = doc.createElement("Directory") ;
d.setAttribute(QString("name"),QString::fromUtf8(di.name.c_str())) ;
if(!recursExportToXml(doc,d,di))
return false; return false;
e.appendChild(d) ; if (!fileName.endsWith("." + RsCollection::ExtensionString))
fileName += "." + RsCollection::ExtensionString ;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
return save(fileName);
}
bool RsCollection::openNewColl(QWidget *parent, QString fileName)
{
if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE
, QApplication::translate("RsCollectionFile", "Create collection file")
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")"
, fileName,0, QFileDialog::DontConfirmOverwrite))
return false;
if (!fileName.endsWith("." + RsCollection::ExtensionString))
fileName += "." + RsCollection::ExtensionString ;
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
QFile file(fileName) ;
if(file.exists())
{
if (!checkFile(fileName,true)) return false;
QMessageBox mb;
mb.setText(tr("Save Collection File."));
mb.setInformativeText(tr("File already exists.")+"\n"+tr("What do you want to do?"));
QAbstractButton *btnOwerWrite = mb.addButton(tr("Overwrite"), QMessageBox::YesRole);
QAbstractButton *btnMerge = mb.addButton(tr("Merge"), QMessageBox::NoRole);
QAbstractButton *btnCancel = mb.addButton(tr("Cancel"), QMessageBox::ResetRole);
mb.setIcon(QMessageBox::Question);
mb.exec();
if (mb.clickedButton()==btnOwerWrite) {
//Nothing to do _xml_doc already up to date
} else if (mb.clickedButton()==btnMerge) {
//Open old file to merge it with _xml_doc
QDomDocument qddOldFile("RsCollection");
if (qddOldFile.setContent(&file)) {
QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement();
std::vector<ColFileInfo> colOldFileInfos;
recursCollectColFileInfos(docOldElem,colOldFileInfos,QString(),false);
QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement();
for(uint32_t i = 0;i<colOldFileInfos.size();++i){
recursAddElements(_xml_doc,colOldFileInfos[i],root) ;
}
} }
return true; } else if (mb.clickedButton()==btnCancel) {
return false;
} else {
return false;
}
}//if(file.exists())
_fileName=fileName;
std::vector<ColFileInfo> colFileInfos ;
recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ;
RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos,true);
connect(rcd,SIGNAL(saveColl(std::vector<ColFileInfo>, QString)),this,SLOT(saveColl(std::vector<ColFileInfo>, QString))) ;
_saved=false;
rcd->exec() ;
delete rcd;
return _saved;
} }
qulonglong RsCollection::count() const bool RsCollection::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/)
{ {
return mFileTree->numFiles(); if (load(fileName, showError)) {
std::vector<ColFileInfo> colFileInfos ;
recursCollectColFileInfos(_xml_doc.documentElement(),colFileInfos,QString(),false) ;
RsCollectionDialog* rcd = new RsCollectionDialog(fileName, colFileInfos, true, readOnly);
connect(rcd,SIGNAL(saveColl(std::vector<ColFileInfo>, QString)),this,SLOT(saveColl(std::vector<ColFileInfo>, QString))) ;
_saved=false;
rcd->exec() ;
delete rcd;
return _saved;
}
return false;
} }
qulonglong RsCollection::size() qulonglong RsCollection::size()
{ {
return mFileTree->totalFileSize(); QDomElement docElem = _xml_doc.documentElement();
std::vector<ColFileInfo> colFileInfos;
recursCollectColFileInfos(docElem, colFileInfos, QString(),false);
uint64_t size = 0;
for (uint32_t i = 0; i < colFileInfos.size(); ++i) {
size += colFileInfos[i].size;
}
return size;
} }
bool RsCollection::isCollectionFile(const QString &fileName) bool RsCollection::isCollectionFile(const QString &fileName)
@ -406,42 +557,14 @@ bool RsCollection::isCollectionFile(const QString &fileName)
return (ext == RsCollection::ExtensionString); return (ext == RsCollection::ExtensionString);
} }
void RsCollection::updateHashes(const std::map<RsFileHash,RsFileHash>& old_to_new_hashes) void RsCollection::saveColl(std::vector<ColFileInfo> colFileInfos, const QString &fileName)
{ {
for(auto it:old_to_new_hashes)
{
auto fit = mHashes.find(it.first);
if(fit == mHashes.end()) QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement();
{ while (root.childNodes().count()>0) root.removeChild(root.firstChild());
RsErr() << "Could not find hash " << it.first << " in RsCollection list of hashes. This is a bug." ; for(uint32_t i = 0;i<colFileInfos.size();++i)
return ; recursAddElements(_xml_doc,colFileInfos[i],root) ;
}
const auto& fd(mFileTree->fileData(fit->second)); _saved=save(fileName);
if(fd.hash != it.first)
{
RsErr() << "Mismatch hash for file " << fd.name << " (found " << fd.hash << " instead of " << it.first << ") in RsCollection list of hashes. This is a bug." ;
return ;
}
mFileTree->updateFile(fit->second,fd.name,it.second,fd.size);
}
}
bool RsCollection::removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index)
{
return mFileTree->removeFile(index_to_remove,parent_index);
}
bool RsCollection::removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index)
{
return mFileTree->removeDirectory(index_to_remove,parent_index);
}
void RsCollection::cleanup()
{
RsDbg() << "Cleaning up RsCollection with " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files." ;
mFileTree = RsFileTree::fromTreeCleaned(*mFileTree);
RsDbg() << "Simplified to " << mFileTree->numDirs() << " dirs and " << mFileTree->numFiles() << " files.";
} }

View File

@ -26,6 +26,7 @@
#pragma once #pragma once
#include <QObject>
#include <QString> #include <QString>
#include <QDomDocument> #include <QDomDocument>
#include <QFile> #include <QFile>
@ -52,70 +53,66 @@ public:
}; };
Q_DECLARE_METATYPE(ColFileInfo) Q_DECLARE_METATYPE(ColFileInfo)
class RsCollection class RsCollection : public QObject
{ {
Q_OBJECT
public: public:
enum class RsCollectionErrorCode:uint8_t {
COLLECTION_NO_ERROR = 0x00,
UNKNOWN_ERROR = 0x01,
FILE_READ_ERROR = 0x02,
FILE_CONTAINS_HARMFUL_STRINGS = 0x03,
INVALID_ROOT_NODE = 0x04,
XML_PARSING_ERROR = 0x05
};
RsCollection();
RsCollection(const RsCollection&);
RsCollection(const std::vector<DirDetails>& file_entries, FileSearchFlags flags) ;
RsCollection(const RsFileTree& ft);
RsCollection(const QString& filename,RsCollectionErrorCode& error_code);
static QString errorString(RsCollectionErrorCode code);
RsCollection(QObject *parent = 0) ;
// create from list of files and directories
RsCollection(const std::vector<DirDetails>& file_entries, FileSearchFlags flags, QObject *parent = 0) ;
RsCollection(const RsFileTree& fr);
virtual ~RsCollection() ; virtual ~RsCollection() ;
void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash,RsFileTree::DirIndex parent_index=0) ; void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ;
void merge_in(const RsFileTree& tree,RsFileTree::DirIndex parent_index=0) ; void merge_in(const RsFileTree& tree) ;
bool removeFile(RsFileTree::FileIndex index_to_remove,RsFileTree::DirIndex parent_index);
bool removeDirectory(RsFileTree::DirIndex index_to_remove,RsFileTree::DirIndex parent_index);
void cleanup(); // cleans up the collection, which may contain unreferenced files/dirs after lazy editing.
static const QString ExtensionString ; static const QString ExtensionString ;
// Loads file from disk.
bool load(QWidget *parent);
bool load(const QString& fileName, bool showError = true);
// Save to disk // Save to disk
bool save(QWidget *parent) const ;
bool save(const QString& fileName) const ; bool save(const QString& fileName) const ;
// returns the file tree // Open new collection
const RsFileTree& fileTree() const { return *mFileTree; } bool openNewColl(QWidget *parent, QString fileName = "");
// total size of files in the collection // Open existing collection
bool openColl(const QString& fileName, bool readOnly = false, bool showError = true);
// Download the content.
void downloadFiles() const ;
// Auto Download all the content.
void autoDownloadFiles() const ;
qulonglong size(); qulonglong size();
// total number of files in the collection
qulonglong count() const;
static bool isCollectionFile(const QString& fileName); static bool isCollectionFile(const QString& fileName);
void updateHashes(const std::map<RsFileHash,RsFileHash>& old_to_new_hashes); private slots:
void saveColl(std::vector<ColFileInfo> colFileInfos, const QString& fileName);
private: private:
bool recursExportToXml(QDomDocument& doc,QDomElement& e,const RsFileTree::DirData& dd) const; void recursAddElements(QDomDocument&, const DirDetails&, QDomElement&, FileSearchFlags flags) const ;
bool recursParseXml(QDomDocument& doc, const QDomNode &e, RsFileTree::DirIndex dd) ; void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const;
void recursAddElements(
// This function is used to populate a RsCollection from locally or remotly shared files. QDomDocument& doc, const RsFileTree& ft, uint32_t index,
void recursAddElements(RsFileTree::DirIndex parent, const DirDetails& dd, FileSearchFlags flags) ; QDomElement& e ) const;
// This function is used to merge an existing RsFileTree into the RsCollection
void recursMergeTree(RsFileTree::DirIndex parent, const RsFileTree& tree, const RsFileTree::DirData &dd);
void recursCollectColFileInfos(const QDomElement&,std::vector<ColFileInfo>& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ;
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this // check that the file is a valid rscollection file, and not a lol bomb or some shit like this
static bool checkFile(const QString &fileName, RsCollectionErrorCode &error); static bool checkFile(const QString &fileName, bool showError);
// Auto Download recursively. // Auto Download recursively.
void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ; void autoDownloadFiles(ColFileInfo colFileInfo, QString dlDir) const ;
std::unique_ptr<RsFileTree> mFileTree; QDomDocument _xml_doc ;
std::map<RsFileHash,RsFileTree::FileIndex> mHashes; // used to efficiently update files being hashed QString _fileName ;
bool _saved;
QDomElement _root ;
friend class RsCollectionDialog ; friend class RsCollectionDialog ;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -18,10 +18,8 @@
* * * *
*******************************************************************************/ *******************************************************************************/
#include <set>
#include "ui_RsCollectionDialog.h" #include "ui_RsCollectionDialog.h"
#include "RsCollection.h" #include "RsCollection.h"
#include "RsCollectionModel.h"
#include <QFileSystemModel> #include <QFileSystemModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
@ -32,45 +30,33 @@ class RsCollectionDialog: public QDialog
Q_OBJECT Q_OBJECT
public: public:
RsCollectionDialog(const QString& filename
, const std::vector<ColFileInfo> &colFileInfos
, const bool& creation
, const bool& readOnly = false) ;
virtual ~RsCollectionDialog(); virtual ~RsCollectionDialog();
// Open new collection
static bool openNewCollection(const RsFileTree &tree = RsFileTree());
// Edit existing collection
static bool editExistingCollection(const QString& fileName, bool showError = true);
// Open existing collection for download
static bool openExistingCollection(const QString& fileName, bool showError = true);
// Open existing collection for download
static bool downloadFiles(const RsCollection& collection);
protected: protected:
static QString errorString(RsCollection::RsCollectionErrorCode code); bool eventFilter(QObject *obj, QEvent *ev);
void init(const QString& collectionFileName);
enum RsCollectionDialogMode {
UNKNOWN = 0x00,
EDIT = 0x01,
DOWNLOAD = 0x02,
};
RsCollectionDialog(const QString& filename, RsCollectionDialogMode mode) ;
RsCollectionDialog(const RsCollection& coll, RsCollectionDialogMode mode) ;
private slots: private slots:
void directoryLoaded(QString dirLoaded); void directoryLoaded(QString dirLoaded);
void updateSizes() ; void updateSizes() ;
void changeFileName() ; void changeFileName() ;
void addSelection() ; void add() ;
void addSelectionRecursive() ; void addRecursive() ;
void remove() ; void remove() ;
void chooseDestinationDirectory(); void chooseDestinationDirectory();
void setDestinationDirectory(); void setDestinationDirectory();
void openDestinationDirectoryMenu(); void openDestinationDirectoryMenu();
void processItem(QMap<QString, QString> &dirToAdd
, int &index
, ColFileInfo &parent
) ;
void makeDir() ; void makeDir() ;
void fileHashingFinished(QList<HashedFile> hashedFiles) ; void fileHashingFinished(QList<HashedFile> hashedFiles) ;
void itemChanged(QTreeWidgetItem* item,int col) ;
void updateRemoveDuplicate(bool checked);
void cancel() ; void cancel() ;
void download() ; void download() ;
void save() ; void save() ;
@ -80,20 +66,26 @@ signals:
private: private:
void processSettings(bool bLoad) ; void processSettings(bool bLoad) ;
void addSelection(bool recursive) ; QTreeWidgetItem* getRootItem();
bool updateList();
bool addChild(QTreeWidgetItem *parent, const std::vector<ColFileInfo> &child);
bool removeItem(QTreeWidgetItem *item, bool &removeOnlyFile) ;
void addRecursive(bool recursive) ;
bool addAllChild(QFileInfo &fileInfoParent
, QMap<QString, QString > &dirToAdd
, QStringList &fileToHash
, int &count);
void saveChild(QTreeWidgetItem *parentItem, ColFileInfo *parentInfo = NULL);
Ui::RsCollectionDialog ui; Ui::RsCollectionDialog ui;
QString _fileName ;
RsCollectionDialogMode _mode; const bool _creationMode ;
const bool _readOnly;
std::vector<ColFileInfo> _newColFileInfos ;
QFileSystemModel *_dirModel; QFileSystemModel *_dirModel;
QSortFilterProxyModel *_tree_proxyModel; QSortFilterProxyModel *_tree_proxyModel;
QItemSelectionModel *_selectionProxy; QItemSelectionModel *_selectionProxy;
bool _dirLoaded; bool _dirLoaded;
QHash<QString,QString> _listOfFilesAddedInDir; QHash<QString,QString> _listOfFilesAddedInDir;
RsCollectionModel *mCollectionModel;
RsCollection *mCollection;
std::map<QString,RsFileHash> mFilesBeingHashed; // map of file path vs. temporary ID used for the file while hashing
}; };

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>761</width> <width>600</width>
<height>434</height> <height>400</height>
</rect> </rect>
</property> </property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
@ -17,7 +17,7 @@
<string>Collection</string> <string>Collection</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset> <iconset resource="../images.qrc">
<normaloff>:/images/mimetypes/rscollection-16.png</normaloff>:/images/mimetypes/rscollection-16.png</iconset> <normaloff>:/images/mimetypes/rscollection-16.png</normaloff>:/images/mimetypes/rscollection-16.png</iconset>
</property> </property>
<property name="sizeGripEnabled"> <property name="sizeGripEnabled">
@ -157,7 +157,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QToolButton" name="_changeFile"> <widget class="QPushButton" name="_changeFile">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>21</width> <width>21</width>
@ -170,10 +170,6 @@
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
<property name="icon">
<iconset resource="../icons.qrc">
<normaloff>:/icons/browsable_blue_128.png</normaloff>:/icons/browsable_blue_128.png</iconset>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -287,7 +283,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/start.png</normaloff>:/images/start.png</iconset> <normaloff>:/images/feedback_arrow.png</normaloff>:/images/feedback_arrow.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -313,7 +309,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset resource="../images.qrc">
<normaloff>:/images/startall.png</normaloff>:/images/startall.png</iconset> <normaloff>:/images/update.png</normaloff>:/images/update.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -338,8 +334,8 @@
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../images.qrc"> <iconset>
<normaloff>:/images/delete.png</normaloff>:/images/delete.png</iconset> <normaloff>:/images/deletemail24.png</normaloff>:/images/deletemail24.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -386,7 +382,7 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QTreeView" name="_fileEntriesTW"> <widget class="QTreeWidget" name="_fileEntriesTW">
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
</property> </property>
@ -402,6 +398,11 @@
<property name="allColumnsShowFocus"> <property name="allColumnsShowFocus">
<bool>true</bool> <bool>true</bool>
</property> </property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget> </widget>
</widget> </widget>
</item> </item>
@ -410,6 +411,26 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="buttons_HL"> <layout class="QHBoxLayout" name="buttons_HL">
<item>
<widget class="QCheckBox" name="_removeDuplicate_CB">
<property name="text">
<string>Remove Duplicate</string>
</property>
</widget>
</item>
<item>
<spacer name="buttons_HSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QLabel" name="downloadFolder_LB"> <widget class="QLabel" name="downloadFolder_LB">
<property name="text"> <property name="text">
@ -430,12 +451,6 @@
</item> </item>
<item> <item>
<widget class="QLineEdit" name="downloadFolder_LE"> <widget class="QLineEdit" name="downloadFolder_LE">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>
@ -447,19 +462,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QPushButton" name="_cancel_PB"> <widget class="QPushButton" name="_cancel_PB">
<property name="text"> <property name="text">
@ -515,7 +517,7 @@
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../images.qrc"/> <include location="../images.qrc"/>
<include location="../icons.qrc"/> <include location="../../../../plugins/FeedReader/gui/FeedReader_images.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -1,616 +0,0 @@
#include <string>
#include <QBrush>
#include "RsCollectionModel.h"
// #define DEBUG_COLLECTION_MODEL 1
static const int COLLECTION_MODEL_FILENAME = 0;
static const int COLLECTION_MODEL_SIZE = 1;
static const int COLLECTION_MODEL_HASH = 2;
static const int COLLECTION_MODEL_COUNT = 3;
static const int COLLECTION_MODEL_NB_COLUMN = 4;
RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent)
: QAbstractItemModel(parent),mCollection(col)
{
postMods();
}
static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIndex& i)
{
return o << ((i.is_file)?("File"):"Dir") << " with index " << (int)i.index ;
}
static std::ostream& operator<<(std::ostream& o,const QModelIndex& i)
{
return o << "QModelIndex (row " << i.row() << ", ref " << i.internalId() << ")" ;
}
#ifdef DEBUG_COLLECTION_MODEL
#endif
// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the
// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the
// architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and
// the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex)
// This way, index 0 is always the top dir.
bool RsCollectionModel::convertIndexToInternalId(const EntryIndex& e,quintptr& ref)
{
ref = (e.index << 1) | e.is_file;
return true;
}
bool RsCollectionModel::convertInternalIdToIndex(quintptr ref, EntryIndex& e)
{
e.is_file = (bool)(ref & 1);
e.index = ref >> 1;
return true;
}
int RsCollectionModel::rowCount(const QModelIndex& parent) const
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Asking rowCount of " << parent << std::endl;
#endif
if(parent.column() >= COLLECTION_MODEL_NB_COLUMN)
return 0;
if(!parent.isValid())
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " root! returning " << mCollection.fileTree().directoryData(0).subdirs.size()
+ mCollection.fileTree().directoryData(0).subfiles.size() << std::endl;
#endif
return mCollection.fileTree().directoryData(0).subdirs.size()
+ mCollection.fileTree().directoryData(0).subfiles.size();
}
EntryIndex i;
if(!convertInternalIdToIndex(parent.internalId(),i))
return 0;
if(i.is_file)
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " file: returning 0" << std::endl;
#endif
return 0;
}
else
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " dir: returning " << mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size()
<< std::endl;
#endif
return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size();
}
}
bool RsCollectionModel::hasChildren(const QModelIndex & parent) const
{
if(!parent.isValid())
return true;
EntryIndex i;
if(!convertInternalIdToIndex(parent.internalId(),i))
return false;
if(i.is_file)
return false;
else if(mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0)
return true;
else
return false;
}
int RsCollectionModel::columnCount(const QModelIndex&) const
{
return COLLECTION_MODEL_NB_COLUMN;
}
QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int role) const
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return tr("File");
case 1: return tr("Size");
case 2: return tr("Hash");
case 3: return tr("Count");
default:
return QVariant();
}
return QVariant();
}
QModelIndex RsCollectionModel::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;
if(!parent.isValid()) // root
{
parent_index.is_file = false;
parent_index.index = 0;
}
else if(!convertInternalIdToIndex(parent.internalId(),parent_index))
return QModelIndex();
if(parent_index.is_file || parent_index.index >= mCollection.fileTree().numDirs())
return QModelIndex();
const auto& parentData(mCollection.fileTree().directoryData(parent_index.index));
if((size_t)row < parentData.subdirs.size())
{
EntryIndex e;
e.is_file = false;
e.index = parentData.subdirs[row];
quintptr ref;
convertIndexToInternalId(e,ref);
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref);
}
if((size_t)row < parentData.subdirs.size() + parentData.subfiles.size())
{
EntryIndex e;
e.is_file = true;
e.index = parentData.subfiles[row - parentData.subdirs.size()];
quintptr ref;
convertIndexToInternalId(e,ref);
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref);
}
return QModelIndex();
}
Qt::ItemFlags RsCollectionModel::flags ( const QModelIndex & index ) const
{
if(index.isValid() && index.column() == COLLECTION_MODEL_FILENAME)
{
EntryIndex e;
if(!convertInternalIdToIndex(index.internalId(),e))
return QAbstractItemModel::flags(index) ;
if(e.is_file)
return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable;
else
return QAbstractItemModel::flags(index) | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
}
return QAbstractItemModel::flags(index) ;
}
QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
{
if(!index.isValid())
return QModelIndex();
EntryIndex i;
if(index.internalId()==0 || !convertInternalIdToIndex(index.internalId(),i))
return QModelIndex();
EntryIndex p;
p.is_file = false; // all parents are directories
int row;
if(i.is_file)
{
p.index = mFileInfos[i.index].parent_index;
row = mFileInfos[i.index].parent_row;
}
else
{
p.index = mDirInfos[i.index].parent_index;
row = mDirInfos[i.index].parent_row;
}
quintptr ref;
convertIndexToInternalId(p,ref);
return createIndex(row,0,ref);
}
QVariant RsCollectionModel::data(const QModelIndex& index, int role) const
{
EntryIndex i;
if(!convertInternalIdToIndex(index.internalId(),i))
return QVariant();
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Asking data of " << i << std::endl;
#endif
switch(role)
{
case Qt::DisplayRole: return displayRole(i,index.column());
case Qt::DecorationRole: return decorationRole(i,index.column());
case Qt::CheckStateRole: return checkStateRole(i,index.column());
case Qt::TextColorRole: return textColorRole(i,index.column());
default:
return QVariant();
}
}
bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,int role)
{
if(!index.isValid())
return false;
EntryIndex e;
if(role==Qt::CheckStateRole && convertInternalIdToIndex(index.internalId(), e))
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl;
#endif
RsFileTree::DirIndex dir_index ;
if(e.is_file)
{
mFileInfos[e.index].is_checked = value.toBool();
dir_index = mFileInfos[e.index].parent_index;
}
else
{
std::function<void(RsFileTree::DirIndex,bool)> recursSetCheckFlag = [&](RsFileTree::DirIndex index,bool s) -> void
{
mDirInfos[index].check_state = (s)?SELECTED:UNSELECTED;
auto& dir_data(mCollection.fileTree().directoryData(index));
mDirInfos[index].total_size = 0;
mDirInfos[index].total_count = 0;
for(uint32_t i=0;i<dir_data.subdirs.size();++i)
{
recursSetCheckFlag(dir_data.subdirs[i],s);
mDirInfos[index].total_size += mDirInfos[dir_data.subdirs[i]].total_size ;
mDirInfos[index].total_count+= mDirInfos[dir_data.subdirs[i]].total_count;
}
for(uint32_t i=0;i<dir_data.subfiles.size();++i)
{
mFileInfos[dir_data.subfiles[i]].is_checked = s;
if(s)
{
mDirInfos[index].total_size += mCollection.fileTree().fileData(dir_data.subfiles[i]).size;
++mDirInfos[index].total_count;
}
}
};
recursSetCheckFlag(e.index,value.toBool());
dir_index = mDirInfos[e.index].parent_index;
}
// now go up the directories and update the check tristate flag, depending on whether the children are all checked/unchecked or mixed.
do
{
auto& dit(mDirInfos[dir_index]);
const RsFileTree::DirData& dir_data(mCollection.fileTree().directoryData(dir_index)); // get the directory data
bool locally_all_checked = true;
bool locally_all_unchecked = true;
dit.total_size = 0;
dit.total_count = 0;
for(uint32_t i=0;i<dir_data.subdirs.size();++i)
{
const auto& dit2(mDirInfos[dir_data.subdirs[i]]);
dit.total_size += dit2.total_size;
dit.total_count += dit2.total_count;
if(dit2.check_state == UNSELECTED || dit2.check_state == PARTIALLY_SELECTED)
locally_all_checked = false;
if(dit2.check_state == SELECTED || dit2.check_state == PARTIALLY_SELECTED)
locally_all_unchecked = false;
}
for(uint32_t i=0;i<dir_data.subfiles.size();++i)
{
const auto& fit2(mFileInfos[dir_data.subfiles[i]]);
if(fit2.is_checked)
{
dit.total_size += mCollection.fileTree().fileData(dir_data.subfiles[i]).size;
++dit.total_count;
locally_all_unchecked = false;
}
else
locally_all_checked = false;
}
if(locally_all_checked)
dit.check_state = SELECTED;
else if(locally_all_unchecked)
dit.check_state = UNSELECTED;
else
dit.check_state = PARTIALLY_SELECTED;
if(dir_index == mCollection.fileTree().root())
break;
else
dir_index = dit.parent_index; // get the directory data
}
while(true);
const auto& top_dir(mCollection.fileTree().directoryData(mCollection.fileTree().root()));
emit dataChanged(createIndex(0,0,(void*)NULL),
createIndex(top_dir.subdirs.size() + top_dir.subfiles.size() - 1,
COLLECTION_MODEL_NB_COLUMN-1,
(void*)NULL),
{ Qt::CheckStateRole });
emit sizesChanged();
return true;
}
else
return QAbstractItemModel::setData(index,value,role);
}
QVariant RsCollectionModel::textColorRole(const EntryIndex& i,int col) const
{
if(i.is_file && mFilesBeingHashed.find(mCollection.fileTree().fileData(i.index).hash) != mFilesBeingHashed.end())
return QVariant(QBrush(QColor::fromRgbF(0.1,0.9,0.2)));
else
return QVariant();
}
QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const
{
if(col == COLLECTION_MODEL_FILENAME)
{
if(i.is_file)
{
if(mFileInfos[i.index].is_checked)
return QVariant(Qt::Checked);
else
return QVariant(Qt::Unchecked);
}
else
{
switch(mDirInfos[i.index].check_state)
{
case SELECTED: return QVariant::fromValue((int)Qt::Checked);
case PARTIALLY_SELECTED: return QVariant::fromValue((int)Qt::PartiallyChecked);
default:
case UNSELECTED: return QVariant::fromValue((int)Qt::Unchecked);
}
}
}
else
return QVariant();
}
QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const
{
switch(col)
{
case COLLECTION_MODEL_FILENAME: if(i.is_file)
return QString::fromUtf8(mCollection.fileTree().fileData(i.index).name.c_str());
else
return QString::fromUtf8(mCollection.fileTree().directoryData(i.index).name.c_str());
case COLLECTION_MODEL_SIZE: if(i.is_file)
return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ;
else
return QVariant((qulonglong)mDirInfos[i.index].total_size);
case COLLECTION_MODEL_HASH: if(i.is_file)
{
if(mFilesBeingHashed.find(mCollection.fileTree().fileData(i.index).hash)!=mFilesBeingHashed.end())
return tr("[File is being hashed]");
else
return QString::fromStdString(mCollection.fileTree().fileData(i.index).hash.toStdString());
}
else
return QVariant();
case COLLECTION_MODEL_COUNT: if(i.is_file)
return (qulonglong)mFileInfos[i.index].is_checked;
else
return (qulonglong)(mDirInfos[i.index].total_count);
}
return QVariant();
}
QVariant RsCollectionModel::sortRole(const EntryIndex& i,int col) const
{
return QVariant();
}
QVariant RsCollectionModel::decorationRole(const EntryIndex& i,int col) const
{
return QVariant();
}
RsCollectionModel::EntryIndex RsCollectionModel::getIndex(const QModelIndex& i) const
{
EntryIndex res;
res.is_file = false;
res.index = 0;
convertInternalIdToIndex(i.internalId(),res);
return res;
}
bool RsCollectionModel::isChecked(EntryIndex i)
{
if(i.is_file)
return mFileInfos[i.index].is_checked;
else
return mDirInfos[i.index].check_state != DirCheckState::UNSELECTED;
}
void RsCollectionModel::notifyFilesBeingHashed(const std::list<RsFileHash>& files)
{
mFilesBeingHashed.insert(files.begin(),files.end());
}
void RsCollectionModel::fileHashingFinished(const RsFileHash& hash)
{
mFilesBeingHashed.erase(hash);
}
void RsCollectionModel::preMods()
{
mUpdating = true;
emit layoutAboutToBeChanged();
}
void RsCollectionModel::postMods()
{
// update all the local structures
mDirInfos.clear();
mFileInfos.clear();
mDirInfos.resize(mCollection.fileTree().numDirs());
mFileInfos.resize(mCollection.fileTree().numFiles());
mDirInfos[0].parent_index = 0;
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Updating from tree: " << std::endl;
#endif
recursUpdateLocalStructures(mCollection.fileTree().root(),0);
mUpdating = false;
emit layoutChanged();
emit sizesChanged();
// debugDump();
}
void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,int depth)
{
uint64_t total_size = 0;
uint64_t total_count = 0;
bool all_checked = true;
bool all_unchecked = false;
const auto& dd(mCollection.fileTree().directoryData(dir_index));
for(uint32_t i=0;i<dd.subdirs.size();++i)
{
#ifdef DEBUG_COLLECTION_MODEL
for(int j=0;j<depth;++j) std::cerr << " ";
std::cerr << "Dir \"" << mCollection.fileTree().directoryData(dd.subdirs[i]).name << "\"" << std::endl ;
#endif
recursUpdateLocalStructures(dd.subdirs[i],depth+1);
auto& ref(mDirInfos[dd.subdirs[i]]);
total_size += ref.total_size;
total_count += ref.total_count;
ref.parent_index = dir_index;
ref.parent_row = i;
all_checked = all_checked && (ref.check_state == SELECTED);
all_unchecked = all_unchecked && (ref.check_state == UNSELECTED);
}
for(uint32_t i=0;i<dd.subfiles.size();++i)
{
#ifdef DEBUG_COLLECTION_MODEL
for(int j=0;j<depth;++j) std::cerr << " ";
std::cerr << "File \"" << mCollection.fileTree().fileData(dd.subfiles[i]).name << "\"" << std::endl;
#endif
auto& ref(mFileInfos[dd.subfiles[i]]);
if(ref.is_checked)
{
total_size += mCollection.fileTree().fileData(dd.subfiles[i]).size;
++total_count;
}
ref.parent_index = dir_index;
ref.parent_row = i + dd.subdirs.size();
all_checked = all_checked && ref.is_checked;
all_unchecked = all_unchecked && !ref.is_checked;
}
auto& r(mDirInfos[dir_index]);
r.total_size = total_size;
r.total_count = total_count;
if(all_checked)
r.check_state = SELECTED;
else if(all_unchecked)
r.check_state = UNSELECTED;
else
r.check_state = PARTIALLY_SELECTED;
}
void RsCollectionModel::debugDump()
{
std::function<void(RsFileTree::DirIndex,int)> recursDump = [&](RsFileTree::DirIndex indx,int depth) {
const auto& dir_data(mCollection.fileTree().directoryData(indx));
for(int i=0;i<depth;++i) std::cerr << " ";
std::cerr << "Directory: \"" << dir_data.name << "\" total_size: " << mDirInfos[indx].total_size << " cnt: " << mDirInfos[indx].total_count << std::endl;
for(uint32_t i=0;i<dir_data.subdirs.size();++i)
recursDump(dir_data.subdirs[i],depth+1);
for(uint32_t i=0;i<dir_data.subfiles.size();++i)
{
for(int i=0;i<depth+1;++i) std::cerr << " ";
std::cerr << "File: \"" << mCollection.fileTree().fileData(dir_data.subfiles[i]).name << "\"" << std::endl;
}
};
std::cerr << "mCollectionModel data: " << std::endl;
recursDump(mCollection.fileTree().root(),0);
std::function<void(QModelIndex index,int)> recursDump2 = [&](QModelIndex indx,int depth) {
for(int i=0;i<depth;++i) std::cerr << " ";
EntryIndex entry;
convertInternalIdToIndex(indx.internalId(),entry);
std::cerr << "Index: " << indx << " has_children: " << RsCollectionModel::hasChildren(indx)
<< ", rowCount: " << RsCollectionModel::rowCount(indx)
<< ", internalId: " << (uint64_t)indx.internalId()
<< ", type: " << (entry.is_file?"file":"dir") << " number " << entry.index
<< ", prow: " << (entry.is_file?mFileInfos[entry.index].parent_row:mDirInfos[entry.index].parent_row)
<< ", parent: " << RsCollectionModel::parent(indx)
<< ", display role: \"" << displayRole(entry,0).toString().toStdString()
<< std::endl;
for(int i=0;i<RsCollectionModel::rowCount(indx);++i)
recursDump2(RsCollectionModel::index(i,0,indx),depth+1);
};
std::cerr << "mCollectionModel index structure: " << std::endl;
recursDump2(QModelIndex(),0);
std::cerr << "mCollectionModel internal data: " << std::endl;
std::cerr << "Directories: "<< std::endl;
for(uint32_t i=0;i<mCollection.fileTree().numDirs();++i)
std::cerr << " " << i << ": "<< mCollection.fileTree().directoryData(i).name << std::endl;
std::cerr << "Files: "<< std::endl;
for(uint32_t i=0;i<mCollection.fileTree().numFiles();++i)
std::cerr << " " << i << ": " << mCollection.fileTree().fileData(i).name << std::endl;
}

View File

@ -1,108 +0,0 @@
#include <QAbstractItemModel>
#include "RsCollection.h"
class RsCollectionModel: public QAbstractItemModel
{
Q_OBJECT
public:
enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2, FilterRole = Qt::UserRole+3 };
RsCollectionModel(const RsCollection& col, QObject *parent = 0);
virtual ~RsCollectionModel() = default;
/* Callback from Core */
void preMods(); // always call this before updating the RsCollection!
void postMods(); // always call this after updating the RsCollection!
/* Callback from GUI */
void update() ;
void filterItems(const std::list<std::string>& keywords, uint32_t& found) ;
// Overloaded from QAbstractItemModel
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const override;
virtual QModelIndex parent ( const QModelIndex & index ) const override;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual bool setData(const QModelIndex& index,const QVariant& value,int role) override;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override;
#ifdef TODO
virtual QStringList mimeTypes () const override;
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override;
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
virtual Qt::DropActions supportedDragActions() const override;
#endif
#endif
struct EntryIndex {
bool is_file; // false=dir, true=file
uint64_t index;
};
uint64_t totalSize() const { return mDirInfos[0].total_size; }
uint64_t totalSelected() const { return mDirInfos[0].total_count; }
void notifyFilesBeingHashed(const std::list<RsFileHash>& files);
void fileHashingFinished(const RsFileHash& hash);
bool isChecked(EntryIndex);
EntryIndex getIndex(const QModelIndex& i) const;
signals:
void sizesChanged(); // tells that the total size of the top level dir has changed (due to selection)
private:
static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref);
static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e);
void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index, int depth);
QVariant displayRole(const EntryIndex&,int col) const ;
QVariant sortRole(const EntryIndex&,int col) const ;
QVariant decorationRole(const EntryIndex&,int col) const ;
QVariant checkStateRole(const EntryIndex& i,int col) const;
QVariant textColorRole(const EntryIndex& i,int col) const;
//QVariant filterRole(const DirDetails& details,int coln) const;
void debugDump();
bool mUpdating ;
const RsCollection& mCollection;
enum DirCheckState: uint8_t {
UNSELECTED = 0x00,
PARTIALLY_SELECTED = 0x01,
SELECTED = 0x02,
};
struct ModelDirInfo {
ModelDirInfo() :parent_index(0),parent_row(0),check_state(SELECTED),total_size(0),total_count(0){}
RsFileTree::DirIndex parent_index; // index of the parent
RsFileTree::DirIndex parent_row; // row of that child, in this parent
DirCheckState check_state;
uint64_t total_size;
uint64_t total_count;
};
struct ModelFileInfo {
ModelFileInfo() :parent_index(0),parent_row(0),is_checked(true){}
RsFileTree::DirIndex parent_index; // index of the parent
RsFileTree::DirIndex parent_row; // row of that child, in this parent
bool is_checked;
};
std::vector<ModelFileInfo> mFileInfos;
std::vector<ModelDirInfo> mDirInfos;
std::set<RsFileHash> mFilesBeingHashed;
// std::set<void*> mFilteredPointers ;
};

View File

@ -21,13 +21,19 @@
#include <stdexcept> #include <stdexcept>
#include <QDesktopServices> #include <QDesktopServices>
#include <QUrl> #include <QUrl>
#include "RsCollectionDialog.h" #include "RsCollection.h"
#include "RsUrlHandler.h" #include "RsUrlHandler.h"
bool RsUrlHandler::openUrl(const QUrl& url) bool RsUrlHandler::openUrl(const QUrl& url)
{ {
if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString)) if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString))
return RsCollectionDialog::openExistingCollection(url.toLocalFile()); {
RsCollection collection ;
if(collection.load(url.toLocalFile()))
{
collection.downloadFiles() ;
return true;
}
}
return QDesktopServices::openUrl(url) ; return QDesktopServices::openUrl(url) ;
} }

View File

@ -131,19 +131,15 @@ void GxsCommentDialog::idChooserReady()
void GxsCommentDialog::voterSelectionChanged( int index ) void GxsCommentDialog::voterSelectionChanged( int index )
{ {
#ifdef DEBUG_COMMENT_DIALOG
std::cerr << "GxsCommentDialog::voterSelectionChanged(" << index << ")"; std::cerr << "GxsCommentDialog::voterSelectionChanged(" << index << ")";
std::cerr << std::endl; std::cerr << std::endl;
#endif
RsGxsId voterId; RsGxsId voterId;
switch (ui->idChooser->getChosenId(voterId)) { switch (ui->idChooser->getChosenId(voterId)) {
case GxsIdChooser::KnowId: case GxsIdChooser::KnowId:
case GxsIdChooser::UnKnowId: case GxsIdChooser::UnKnowId:
#ifdef DEBUG_COMMENT_DIALOG
std::cerr << "GxsCommentDialog::voterSelectionChanged() => " << voterId; std::cerr << "GxsCommentDialog::voterSelectionChanged() => " << voterId;
std::cerr << std::endl; std::cerr << std::endl;
#endif
ui->treeWidget->setVoteId(voterId); ui->treeWidget->setVoteId(voterId);
break; break;
@ -164,10 +160,8 @@ void GxsCommentDialog::setCommentHeader(QWidget *header)
return; return;
} }
#ifdef DEBUG_COMMENT_DIALOG
std::cerr << "GxsCommentDialog::setCommentHeader() Adding header to ui,postFrame"; std::cerr << "GxsCommentDialog::setCommentHeader() Adding header to ui,postFrame";
std::cerr << std::endl; std::cerr << std::endl;
#endif
//header->setParent(ui->postFrame); //header->setParent(ui->postFrame);
//ui->postFrame->setVisible(true); //ui->postFrame->setVisible(true);

Some files were not shown because too many files have changed in this diff Show More