mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-07-21 13:49:04 -04:00
Merge branch 'RetroShare:master' into picturepreview-fileattachments-forums
This commit is contained in:
commit
26fececb2b
493 changed files with 71323 additions and 74304 deletions
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team <contact@retroshare.cc>
|
||||
# SPDX-FileCopyrightText: (C) 2004-2022 Retroshare Team <contact@retroshare.cc>
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
*.o
|
||||
|
@ -16,4 +16,22 @@ Thumbs.db
|
|||
.kdev4
|
||||
*.kdev4
|
||||
|
||||
.qmake.stash
|
||||
|
||||
!supportlibs/libsam3/Makefile
|
||||
|
||||
# QtCreator cruft
|
||||
*CMakeLists.txt.user*
|
||||
|
||||
# Build artifacts
|
||||
/jsonapi-generator/src/jsonapi-generator
|
||||
/jsonapi-generator/src/jsonapi-generator-doxygen-final.conf
|
||||
/jsonapi-generator/src/jsonapi-includes.inl
|
||||
/jsonapi-generator/src/jsonapi-wrappers.inl
|
||||
/jsonapi-generator/src/xml/
|
||||
/retroshare-friendserver/src/retroshare-friendserver
|
||||
/retroshare-gui/src/include/
|
||||
/retroshare-gui/src/retroshare
|
||||
/retroshare-gui/src/temp/
|
||||
/retroshare-service/src/retroshare-service
|
||||
/*.tar.?z
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
image: docker:stable
|
||||
image: docker:latest
|
||||
|
||||
services:
|
||||
- docker:stable-dind
|
||||
- docker:dind
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
@ -18,6 +18,7 @@ variables:
|
|||
build-ubuntu-test-image:
|
||||
stage: build
|
||||
script:
|
||||
- docker --version
|
||||
- >
|
||||
docker login "$CI_REGISTRY"
|
||||
--username "$CI_REGISTRY_USER"
|
||||
|
@ -35,6 +36,7 @@ build-ubuntu-test-image:
|
|||
test-ubuntu:
|
||||
stage: test
|
||||
script:
|
||||
- docker --version
|
||||
- >
|
||||
docker login "$CI_REGISTRY"
|
||||
--username "$CI_REGISTRY_USER"
|
||||
|
@ -67,43 +69,3 @@ test-ubuntu:
|
|||
docker exec retroshare
|
||||
curl --verbose http://127.0.0.1:9092/rsMsgs/getChatLobbyList | jq
|
||||
- docker container stop retroshare
|
||||
|
||||
build-android-arm-apk:
|
||||
stage: build
|
||||
script:
|
||||
- mkdir Dockercontext
|
||||
- >
|
||||
docker build -t retroshare:android_arm_latest
|
||||
$($CI_PROJECT_DIR/build_scripts/GitlabCI/getRepoArgs.sh)
|
||||
--build-arg RS_SERVICE_QMAKE_EXTRA_OPTS="$RS_SERVICE_QMAKE_EXTRA_OPTS"
|
||||
--file $CI_PROJECT_DIR/build_scripts/GitlabCI/Android.Dockerfile
|
||||
Dockercontext
|
||||
# see https://stackoverflow.com/a/59055906
|
||||
- >
|
||||
docker cp
|
||||
$(docker create --rm retroshare:android_arm_latest):/retroshare-service-android-build/android-build/build/outputs/apk/debug/android-build-debug.apk
|
||||
$CI_PROJECT_DIR/RetroShare_Android_Service-arm.apk
|
||||
artifacts:
|
||||
paths:
|
||||
- RetroShare_Android_Service-arm.apk
|
||||
|
||||
# Use separate runner to avoid no space left on device
|
||||
build-android-arm64-apk:
|
||||
stage: build
|
||||
script:
|
||||
- mkdir Dockercontext
|
||||
- >
|
||||
docker build -t retroshare:android_arm64_latest
|
||||
$($CI_PROJECT_DIR/build_scripts/GitlabCI/getRepoArgs.sh)
|
||||
--build-arg ANDROID_PLATFORM_VER=21
|
||||
--build-arg ANDROID_NDK_ARCH=arm64
|
||||
--build-arg RS_SERVICE_QMAKE_EXTRA_OPTS="$RS_SERVICE_QMAKE_EXTRA_OPTS"
|
||||
--file $CI_PROJECT_DIR/build_scripts/GitlabCI/Android.Dockerfile
|
||||
Dockercontext
|
||||
- >
|
||||
docker cp
|
||||
$(docker create --rm retroshare:android_arm64_latest):/retroshare-service-android-build/android-build/build/outputs/apk/debug/android-build-debug.apk
|
||||
$CI_PROJECT_DIR/RetroShare_Android_Service-arm64.apk
|
||||
artifacts:
|
||||
paths:
|
||||
- RetroShare_Android_Service-arm64.apk
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -10,7 +10,8 @@
|
|||
[submodule "supportlibs/udp-discovery-cpp"]
|
||||
path = supportlibs/udp-discovery-cpp
|
||||
url = https://github.com/truvorskameikin/udp-discovery-cpp.git
|
||||
branch = develop
|
||||
branch = master
|
||||
# develop branch was removed we were using it at commit f3a3103a6c52e5707629e8d0a7e279a7758fe845
|
||||
[submodule "supportlibs/rapidjson"]
|
||||
path = supportlibs/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson.git
|
||||
|
@ -30,5 +31,8 @@
|
|||
branch = master
|
||||
[submodule "libretroshare"]
|
||||
path = libretroshare
|
||||
url = ../libretroshare
|
||||
url = https://github.com/RetroShare/libretroshare.git
|
||||
branch = master
|
||||
[submodule "retroshare-webui"]
|
||||
path = retroshare-webui
|
||||
url = https://github.com/RetroShare/RSNewWebUI.git
|
||||
|
|
|
@ -9,9 +9,10 @@ RetroShare provides file sharing, chat, messages, forums, channels and more.
|
|||
|
||||
.Build Status
|
||||
|===============================================================================
|
||||
|GNU/Linux, Android (via Gitlab CI) | image:https://gitlab.com/RetroShare/RetroShare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/RetroShare/-/commits/master",title="pipeline status"]
|
||||
|GNU/Linux (via Gitlab CI) | image:https://gitlab.com/RetroShare/RetroShare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/RetroShare/-/commits/master",title="pipeline status"]
|
||||
|Windows (via AppVeyor) | image:https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true[link="https://ci.appveyor.com/project/RetroShare58622/retroshare"]
|
||||
|macOS, (via Travis CI) | image:https://app.travis-ci.com/RetroShare/RetroShare.svg?branch=master[link="https://app.travis-ci.com/github/RetroShare/RetroShare"]
|
||||
|libretroshare GNU/Linux, Android (via Gitlab CI) | image:https://gitlab.com/RetroShare/libretroshare/badges/master/pipeline.svg[link="https://gitlab.com/RetroShare/libretroshare/-/commits/master",title="pipeline status"]
|
||||
|===============================================================================
|
||||
|
||||
== Get the source
|
||||
|
|
|
@ -68,6 +68,13 @@ retroshare_plugins {
|
|||
plugins.target = plugins
|
||||
}
|
||||
|
||||
rs_webui {
|
||||
SUBDIRS += retroshare-webui
|
||||
retroshare-webui.file = retroshare-webui/webui.pro
|
||||
retroshare-webui.target = rs_webui
|
||||
retroshare-webui.depends = retroshare_gui
|
||||
}
|
||||
|
||||
wikipoos {
|
||||
SUBDIRS += pegmarkdown
|
||||
pegmarkdown.file = supportlibs/pegmarkdown/pegmarkdown.pro
|
||||
|
|
|
@ -258,10 +258,10 @@ after_build:
|
|||
# artifacts configuration #
|
||||
#---------------------------------#
|
||||
|
||||
#artifacts:
|
||||
# - path: '**\*.exe'
|
||||
# - path: filelist.txt
|
||||
# - path: $(RS_DEPLOY)
|
||||
artifacts:
|
||||
- path: '**\*.exe'
|
||||
- path: filelist.txt
|
||||
- path: $(RS_DEPLOY)
|
||||
|
||||
#
|
||||
# # pushing a single file
|
||||
|
|
|
@ -12,16 +12,26 @@
|
|||
## To run the container
|
||||
# docker run -it -p 127.0.0.1:9092:9092 "${CI_REGISTRY_IMAGE}" retroshare-service --jsonApiPort 9092 --jsonApiBindAddress 0.0.0.0
|
||||
|
||||
FROM ubuntu
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV APT_UNAT="--assume-yes --quiet"
|
||||
|
||||
RUN apt-get update -y && apt-get upgrade -y -qq && \
|
||||
apt-get install -y -qq build-essential cimg-dev libssl-dev libbz2-dev \
|
||||
libsqlite3-dev \
|
||||
libsqlcipher-dev libupnp-dev pkg-config libz-dev \
|
||||
qt5-default libxapian-dev qttools5-dev doxygen rapidjson-dev \
|
||||
git cmake curl
|
||||
RUN apt-get update $APT_UNAT && \
|
||||
apt-get upgrade --show-upgraded $APT_UNAT && \
|
||||
apt-get clean $APT_UNAT && \
|
||||
apt-get install --no-install-recommends $APT_UNAT \
|
||||
bash build-essential cimg-dev libssl-dev libbz2-dev \
|
||||
libminiupnpc-dev \
|
||||
libsqlite3-dev libsqlcipher-dev \
|
||||
pkg-config libz-dev \
|
||||
libxapian-dev doxygen rapidjson-dev \
|
||||
git cmake curl python3
|
||||
|
||||
## Avoid git cloning spuriously failing with
|
||||
# server certificate verification failed. CAfile: none CRLfile: none
|
||||
RUN apt-get install --no-install-recommends $APT_UNAT --reinstall \
|
||||
ca-certificates
|
||||
|
||||
RUN git clone --depth 1 https://github.com/aetilius/pHash.git && \
|
||||
rm -rf pHash-build && mkdir pHash-build && cd pHash-build && \
|
||||
|
@ -30,15 +40,23 @@ RUN git clone --depth 1 https://github.com/aetilius/pHash.git && \
|
|||
rm -rf pHash-build pHash
|
||||
|
||||
ARG FRESHCLONE=0
|
||||
ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
|
||||
ARG REPO_URL=https://github.com/RetroShare/RetroShare.git
|
||||
ARG REPO_BRANCH=master
|
||||
ARG REPO_DEPTH="--depth 2000"
|
||||
RUN git clone $REPO_DEPTH $REPO_URL -b $REPO_BRANCH && cd RetroShare && \
|
||||
git fetch --tags && cd ..
|
||||
RUN mkdir RetroShare-build && cd RetroShare-build && \
|
||||
qmake ../RetroShare \
|
||||
CONFIG+=no_retroshare_plugins \
|
||||
CONFIG+=retroshare_service CONFIG+=no_retroshare_gui \
|
||||
CONFIG+=rs_jsonapi CONFIG+=rs_deep_search && \
|
||||
(make -j$(nproc) || make -j$(nproc) || make) && make install && \
|
||||
RUN git clone $REPO_DEPTH $REPO_URL -b $REPO_BRANCH && \
|
||||
cd RetroShare && \
|
||||
git fetch --tags && \
|
||||
git submodule update --init \
|
||||
libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ \
|
||||
supportlibs/restbed/ && \
|
||||
cd supportlibs/restbed/ && \
|
||||
git submodule update --init \
|
||||
dependency/asio/ dependency/kashmir/ && \
|
||||
cd ../../../
|
||||
|
||||
RUN \
|
||||
mkdir RetroShare-build && cd RetroShare-build && \
|
||||
cmake -B. -S../RetroShare/retroshare-service \
|
||||
-DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON -DRS_WEBUI=ON && \
|
||||
make -j$(nproc) && make install && \
|
||||
cd .. && rm -rf RetroShare-build
|
||||
|
|
|
@ -2,17 +2,19 @@ FROM registry.gitlab.com/retroshare/retroshare:base
|
|||
|
||||
RUN apt-get update -y && apt-get upgrade -y
|
||||
|
||||
ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git
|
||||
ARG REPO_URL=https://github.com/RetroShare/RetroShare.git
|
||||
ARG REPO_BRANCH=master
|
||||
RUN \
|
||||
cd RetroShare && git remote add testing $REPO_URL && \
|
||||
git fetch --tags testing $REPO_BRANCH && \
|
||||
git reset --hard testing/$REPO_BRANCH && \
|
||||
git submodule update --init \
|
||||
libbitdht/ libretroshare/ openpgpsdk/ retroshare-webui/ && \
|
||||
git --no-pager log --max-count 1
|
||||
RUN \
|
||||
mkdir RetroShare-build && cd RetroShare-build && \
|
||||
qmake ../RetroShare CONFIG+=no_retroshare_gui \
|
||||
CONFIG+=retroshare_service \
|
||||
CONFIG+=rs_jsonapi CONFIG+=rs_deep_search && \
|
||||
(make -j$(nproc) || make -j$(nproc) || make) && make install && \
|
||||
cmake -B. -S../RetroShare/retroshare-service \
|
||||
-DRS_FORUM_DEEP_INDEX=ON -DRS_JSON_API=ON -DRS_WEBUI=ON \
|
||||
-DRS_WARN_DEPRECATED=OFF -DRS_WARN_LESS=ON && \
|
||||
make -j$(nproc) && make install && \
|
||||
cd .. && rm -rf RetroShare-build
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit df16cb915465d058c75277678799ce4dadeae287
|
||||
Subproject commit 0a3997cc1355b2c848161dca015b7e2df039707b
|
|
@ -30,32 +30,22 @@ In GitHub Desktop -> Clone Repository -> URL
|
|||
|
||||
Add Repository URL: https://github.com/RetroShare/RetroShare.git and Clone
|
||||
|
||||
## ***Choose if you use MacPort or HomeBrew***
|
||||
## ***Get XCode & MacOSX SDK***
|
||||
|
||||
### MacPort Installation
|
||||
Install XCode following this guide: [XCode](http://guide.macports.org/#installing.xcode)
|
||||
|
||||
Install MacPort and XCode following this guide: [MacPort and 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.
|
||||
|
||||
Start XCode to get it updated and to able C compiler to create executables.
|
||||
If you are running the macOS Catalina >= 10.15, you can install Xcode directly from App Store using the instructions below.
|
||||
|
||||
#### Install libraries
|
||||
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
|
||||
|
||||
$ sudo port -v selfupdate
|
||||
$ sudo port install openssl
|
||||
$ sudo port install miniupnpc
|
||||
$ sudo port install libmicrohttpd
|
||||
To install from App Store:
|
||||
|
||||
For VOIP Plugin:
|
||||
Select [x] menu - > "App Store…".
|
||||
Search for Xcode. Download and install.
|
||||
|
||||
$ sudo port install speex-devel
|
||||
$ sudo port install opencv
|
||||
$ sudo port install ffmpeg
|
||||
|
||||
Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs)
|
||||
|
||||
### HOMEBREW Installation
|
||||
|
||||
Install HomeBrew following this guide: [HomeBrew](http://brew.sh/)
|
||||
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:
|
||||
|
||||
|
@ -63,14 +53,42 @@ Install XCode command line developer tools:
|
|||
|
||||
Start XCode to get it updated and to able C compiler to create executables.
|
||||
|
||||
Get Your MacOSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs)
|
||||
|
||||
## ***Choose if you use MacPort or HomeBrew***
|
||||
|
||||
### MacPort Installation
|
||||
|
||||
Install MacPort following this guide: [MacPort](http://guide.macports.org/#installing.xcode)
|
||||
|
||||
#### Install libraries
|
||||
|
||||
$ sudo port -v selfupdate
|
||||
$ sudo port install openssl
|
||||
$ sudo port install miniupnpc
|
||||
|
||||
For VOIP Plugin:
|
||||
|
||||
$ sudo port install speex-devel
|
||||
$ sudo port install opencv
|
||||
$ sudo port install ffmpeg
|
||||
|
||||
|
||||
### HOMEBREW Installation
|
||||
|
||||
Install HomeBrew following this guide: [HomeBrew](http://brew.sh/)
|
||||
|
||||
#### Install libraries
|
||||
|
||||
$ brew install openssl
|
||||
$ brew install miniupnpc
|
||||
$ brew install libmicrohttpd
|
||||
$ brew install rapidjson
|
||||
$ brew install sqlcipher
|
||||
|
||||
#### Install CMake
|
||||
|
||||
$ brew install cmake
|
||||
|
||||
If you have error in linking, run this:
|
||||
|
||||
$sudo chown -R $(whoami) /usr/local/lib/pkgconfig
|
||||
|
@ -85,8 +103,7 @@ For VOIP Plugin:
|
|||
For FeedReader Plugin:
|
||||
|
||||
$ brew install libxslt
|
||||
|
||||
Get Your OSX SDK if missing: [MacOSX-SDKs](https://github.com/phracker/MacOSX-SDKs)
|
||||
$ brew install libxml2
|
||||
|
||||
## Last Settings
|
||||
|
||||
|
@ -104,11 +121,8 @@ In QtCreator Projects -> Build -> Build Settings -> Build Steps -> Add Additiona
|
|||
|
||||
## Set your Mac OS SDK version
|
||||
|
||||
Edit RetroShare.pro
|
||||
|
||||
CONFIG += c++14 rs_macos11.1
|
||||
|
||||
and then retroshare.pri
|
||||
Edit retroshare.pri and set your installed sdk version example for 11.1 -> rs_macos11.1 (line 135:)
|
||||
|
||||
macx:CONFIG *= rs_macos11.1
|
||||
rs_macos10.8:CONFIG -= rs_macos11.1
|
||||
|
@ -122,7 +136,7 @@ and then retroshare.pri
|
|||
|
||||
## Link Include & Libraries
|
||||
|
||||
Edit your retroshare.pri and add to macx-* section
|
||||
When required edit your retroshare.pri macx-* section, check if the Include and Lib path are correct (macx-* section)
|
||||
|
||||
INCLUDEPATH += "/usr/local/opt/openssl/include"
|
||||
QMAKE_LIBDIR += "/usr/local/opt/openssl/lib"
|
||||
|
@ -131,13 +145,21 @@ Edit your retroshare.pri and add to macx-* section
|
|||
|
||||
alternative via Terminal
|
||||
|
||||
$ 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"
|
||||
$ 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" \
|
||||
CONFIG+=rs_autologin \
|
||||
CONFIG+=rs_use_native_dialogs \
|
||||
CONFIG+=release \
|
||||
..
|
||||
|
||||
For FeedReader Plugin:
|
||||
|
||||
INCLUDEPATH += "/usr/local/opt/libxml2/include/libxml2"
|
||||
|
||||
For building RetroShare with plugins:
|
||||
With plugins:
|
||||
|
||||
$ qmake \
|
||||
INCLUDEPATH+="/usr/local/opt/openssl/include" QMAKE_LIBDIR+="/usr/local/opt/openssl/lib" \
|
||||
|
@ -159,13 +181,30 @@ For building RetroShare with plugins:
|
|||
|
||||
You can now compile RetroShare into Qt Creator or with Terminal
|
||||
|
||||
cd retroshare
|
||||
qmake; make
|
||||
$ cd /path/to/retroshare
|
||||
$ qmake ..
|
||||
$ make
|
||||
|
||||
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*
|
||||
|
||||
## 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
|
||||
|
||||
$ cp \
|
||||
|
@ -173,3 +212,13 @@ You can find the compiled application at *./retroshare/retroshare-gui/src/retros
|
|||
./plugins/VOIP/lib/libVOIP.dylib \
|
||||
./plugins/RetroChess/lib/libRetroChess.dylib \
|
||||
./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
|
||||
|
|
50
build_scripts/OSX/makeOSXPackage.sh
Normal file
50
build_scripts/OSX/makeOSXPackage.sh
Normal file
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh
|
||||
|
||||
APP="RetroShare"
|
||||
RSVERSION="0.6.7a"
|
||||
QTVERSION="Qt-5.14.1"
|
||||
|
||||
# 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
|
||||
|
||||
# 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"
|
|
@ -32,6 +32,16 @@ if not "%ParamNoupdate%"=="1" (
|
|||
if "%ParamIndexing%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-xapian-core mingw-w64-%RsMSYS2Architecture%-libvorbis mingw-w64-%RsMSYS2Architecture%-flac mingw-w64-%RsMSYS2Architecture%-taglib"
|
||||
)
|
||||
|
||||
:: Fix webui compilation (TODO: remove when whole RS switched to cmake)
|
||||
if "%ParamWebui%"=="1" (
|
||||
pushd "%SourcePath%"
|
||||
copy "%SourcePath%\libretroshare\src\jsonapi\jsonapi-generator-doxygen.conf" "%SourcePath%\jsonapi-generator\src\jsonapi-generator-doxygen.conf" %Quite%
|
||||
copy "%SourcePath%\libretroshare\src\jsonapi\async-method-wrapper-template.cpp.tmpl" "%SourcePath%\jsonapi-generator\src\async-method-wrapper-template.cpp.tmpl" %Quite%
|
||||
copy "%SourcePath%\libretroshare\src\jsonapi\method-wrapper-template.cpp.tmpl" "%SourcePath%\jsonapi-generator\src\method-wrapper-template.cpp.tmpl" %Quite%
|
||||
git update-index --assume-unchanged "jsonapi-generator\src\jsonapi-generator-doxygen.conf" "jsonapi-generator\src\async-method-wrapper-template.cpp.tmpl" "jsonapi-generator\src\method-wrapper-template.cpp.tmpl"
|
||||
popd
|
||||
)
|
||||
|
||||
:: Initialize environment
|
||||
call "%~dp0env.bat" %*
|
||||
if errorlevel 2 exit /B 2
|
||||
|
@ -66,6 +76,7 @@ echo %RS_QMAKE_CONFIG% > buildinfo.txt
|
|||
echo %RsBuildConfig% >> buildinfo.txt
|
||||
echo %RsArchitecture% >> buildinfo.txt
|
||||
echo Qt %QtVersion% >> buildinfo.txt
|
||||
echo %RsToolchain% >> buildinfo.txt
|
||||
echo %RsCompiler% >> buildinfo.txt
|
||||
|
||||
call "%ToolsPath%\msys2-path.bat" "%SourcePath%" MSYS2SourcePath
|
||||
|
@ -86,11 +97,6 @@ title Build - %SourceName%-%RsBuildConfig% [make]
|
|||
%EnvMSYS2Cmd% "make -j %CoreCount%"
|
||||
if errorlevel 1 goto error
|
||||
|
||||
:: Webui
|
||||
if "%ParamWebui%"=="1" (
|
||||
call "%~dp0..\tools\webui.bat"
|
||||
)
|
||||
|
||||
:error
|
||||
popd
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
:: Process commandline parameter
|
||||
set Param32=0
|
||||
set Param64=0
|
||||
set ParamRelease=0
|
||||
set ParamDebug=0
|
||||
set ParamAutologin=0
|
||||
|
@ -9,17 +7,40 @@ set ParamTor=0
|
|||
set ParamWebui=0
|
||||
set ParamClang=0
|
||||
set ParamIndexing=0
|
||||
set ParamFriendserver=0
|
||||
set ParamNoupdate=0
|
||||
set CoreCount=%NUMBER_OF_PROCESSORS%
|
||||
set RS_QMAKE_CONFIG=
|
||||
set RsToolchain=
|
||||
set tcc=0
|
||||
|
||||
:parameter_loop
|
||||
if "%~1" NEQ "" (
|
||||
for /f "tokens=1,2 delims==" %%a in ("%~1") do (
|
||||
if "%%~a"=="32" (
|
||||
set Param32=1
|
||||
set RsToolchain=mingw32
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="64" (
|
||||
set Param64=1
|
||||
set RsToolchain=mingw64
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="mingw32" (
|
||||
set RsToolchain=mingw32
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="mingw64" (
|
||||
set RsToolchain=mingw64
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="ucrt64" (
|
||||
set RsToolchain=ucrt64
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="clang64" (
|
||||
set RsToolchain=clang64
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="clang32" (
|
||||
set RsToolchain=clang32
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="clangarm64" (
|
||||
set RsToolchain=clangarm64
|
||||
set /A tcc=tcc+1
|
||||
) else if "%%~a"=="release" (
|
||||
set ParamRelease=1
|
||||
) else if "%%~a"=="debug" (
|
||||
|
@ -38,6 +59,8 @@ if "%~1" NEQ "" (
|
|||
set ParamClang=1
|
||||
) else if "%%~a"=="indexing" (
|
||||
set ParamIndexing=1
|
||||
) else if "%%~a"=="friendserver" (
|
||||
set ParamFriendserver=1
|
||||
) else if "%%~a"=="noupdate" (
|
||||
set ParamNoupdate=1
|
||||
) else if "%%~a"=="CONFIG+" (
|
||||
|
@ -52,22 +75,37 @@ if "%~1" NEQ "" (
|
|||
goto parameter_loop
|
||||
)
|
||||
|
||||
if "%Param32%"=="1" (
|
||||
if "%Param64%"=="1" (
|
||||
echo.
|
||||
echo 32-bit or 64-bit?
|
||||
if %tcc% NEQ 1 (
|
||||
echo Multiple or no toolchain specified
|
||||
goto :usage
|
||||
)
|
||||
|
||||
set RsBit=32
|
||||
if "%RsToolchain%"=="mingw32" (
|
||||
set RsArchitecture=x86
|
||||
set RsMSYS2Architecture=i686
|
||||
)
|
||||
|
||||
if "%Param64%"=="1" (
|
||||
set RsBit=64
|
||||
set MSYSTEM=MINGW32
|
||||
) else if "%RsToolchain%"=="mingw64" (
|
||||
set RsArchitecture=x64
|
||||
set RsMSYS2Architecture=x86_64
|
||||
set MSYSTEM=MINGW64
|
||||
) else if "%RsToolchain%"=="ucrt64" (
|
||||
set RsArchitecture=x64
|
||||
set RsMSYS2Architecture=ucrt-x86_64
|
||||
set MSYSTEM=UCRT64
|
||||
) else if "%RsToolchain%"=="clang64" (
|
||||
set RsArchitecture=x64
|
||||
set RsMSYS2Architecture=clang-x86_64
|
||||
set MSYSTEM=CLANG64
|
||||
set ParamClang=1
|
||||
) else if "%RsToolchain%"=="clang32" (
|
||||
set RsArchitecture=x86
|
||||
set RsMSYS2Architecture=clang-i686
|
||||
set MSYSTEM=CLANG32
|
||||
set ParamClang=1
|
||||
) else if "%RsToolchain%"=="clangarm64" (
|
||||
set RsArchitecture=arm64
|
||||
set RsMSYS2Architecture=clang-aarch64
|
||||
set MSYSTEM=CLANGARM64
|
||||
)
|
||||
|
||||
if "%ParamClang%"=="1" (
|
||||
|
@ -76,8 +114,6 @@ if "%ParamClang%"=="1" (
|
|||
set RsCompiler=GCC
|
||||
)
|
||||
|
||||
if "%RsBit%"=="" goto :usage
|
||||
|
||||
if "%ParamRelease%"=="1" (
|
||||
if "%ParamDebug%"=="1" (
|
||||
echo.
|
||||
|
@ -104,14 +140,21 @@ if "%ParamIndexing%"=="1" (
|
|||
set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_deep_channels_index" "CONFIG+=rs_deep_files_index" "CONFIG+=rs_deep_files_index_ogg" "CONFIG+=rs_deep_files_index_flac" "CONFIG+=rs_deep_files_index_taglib"
|
||||
)
|
||||
|
||||
if "%ParamFriendserver%"=="1" (
|
||||
set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_efs"
|
||||
)
|
||||
|
||||
exit /B 0
|
||||
|
||||
:usage
|
||||
echo.
|
||||
echo Usage: 32^|64 release^|debug [autologin plugins webui singlethread clang indexing noupdate] ["CONFIG+=..."]
|
||||
echo Usage: 32^|64^|other release^|debug [autologin plugins webui singlethread clang indexing friendserver noupdate] ["CONFIG+=..."]
|
||||
echo.
|
||||
echo Mandatory parameter
|
||||
echo 32^|64 32-bit or 64-bit Version
|
||||
echo 32^|64 32-bit or 64-bit version (same as mingw32 or mingw64)
|
||||
echo Or you can specify any other toolchain supported by msys2:
|
||||
echo mingw32^|mingw64^|clang32^|clang64^|ucrt64^|clangarm64
|
||||
echo More info: https://www.msys2.org/docs/environments
|
||||
echo release^|debug Build release or debug version
|
||||
echo.
|
||||
echo Optional parameter (need clean when changed)
|
||||
|
@ -121,6 +164,7 @@ echo webui Enable JsonAPI and pack webui files
|
|||
echo singlethread Use only 1 thread for building
|
||||
echo clang Use clang compiler instead of GCC
|
||||
echo indexing Build with deep channel and file indexing support
|
||||
echo friendserver Enable friendserver support
|
||||
echo noupdate Skip updating the libraries
|
||||
echo "CONFIG+=..." Enable some extra features, you can find the almost complete list in retroshare.pri
|
||||
echo.
|
||||
|
|
|
@ -2,8 +2,6 @@ call "%~dp0env-base.bat" %*
|
|||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
set MSYSTEM=MINGW%RsBit%
|
||||
|
||||
set BuildPath=%EnvRootPath%\builds
|
||||
set DeployPath=%EnvRootPath%\deploy
|
||||
|
||||
|
@ -14,13 +12,13 @@ if not exist "%DeployPath%" mkdir "%DeployPath%"
|
|||
call "%ToolsPath%\get-qt-version.bat" QtVersion
|
||||
if "%QtVersion%"=="" %cecho% error "Cannot get Qt version." & exit /B 1
|
||||
|
||||
set RsMinGWPath=%EnvMSYS2BasePath%\mingw%RsBit%
|
||||
set RsMinGWPath=%EnvMSYS2BasePath%\%RsToolchain%
|
||||
|
||||
set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%RsArchitecture%-%RsCompiler%-%RsBuildConfig%
|
||||
set RsDeployPath=%DeployPath%\Qt-%QtVersion%%RsType%-%RsArchitecture%-%RsCompiler%-%RsBuildConfig%
|
||||
set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%RsToolchain%-%RsCompiler%-%RsBuildConfig%
|
||||
set RsDeployPath=%DeployPath%\Qt-%QtVersion%%RsType%-%RsToolchain%-%RsCompiler%-%RsBuildConfig%
|
||||
set RsPackPath=%DeployPath%
|
||||
set RsArchiveAdd=
|
||||
set RsWebuiPath=%RootPath%\%SourceName%-webui
|
||||
set RsWebuiBuildPath=%RsBuildPath%\retroshare-webui\webui
|
||||
|
||||
if not exist "%~dp0env-mod.bat" goto no_mod
|
||||
call "%~dp0env-mod.bat"
|
||||
|
|
|
@ -105,6 +105,9 @@ copy "%RsBuildPath%\retroshare-nogui\src\%RsBuildConfig%\retroshare*-nogui.exe"
|
|||
copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite%
|
||||
copy "%RsBuildPath%\supportlibs\cmark\build\src\libcmark.dll" "%RsDeployPath%" %Quite%
|
||||
if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite%
|
||||
if exist "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" (
|
||||
copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite%
|
||||
)
|
||||
|
||||
echo copy extensions
|
||||
for /D %%D in ("%RsBuildPath%\plugins\*") do (
|
||||
|
@ -184,12 +187,12 @@ echo copy buildinfo.txt
|
|||
copy "%RsBuildPath%\buildinfo.txt" "%RsDeployPath%" %Quite%
|
||||
|
||||
if "%ParamWebui%"=="1" (
|
||||
if exist "%RsWebuiPath%\webui" (
|
||||
if exist "%RsWebuiBuildPath%" (
|
||||
echo copy webui
|
||||
mkdir "%RsDeployPath%\webui"
|
||||
xcopy /S "%RsWebuiPath%\webui" "%RsDeployPath%\webui" %Quite%
|
||||
xcopy /S "%RsWebuiBuildPath%" "%RsDeployPath%\webui" %Quite%
|
||||
) else (
|
||||
%cecho% error "Webui is enabled, but no webui data found at %RsWebuiPath%\webui"
|
||||
%cecho% error "Webui is enabled, but no webui data found at %RsWebuiBuildPath%"
|
||||
goto error
|
||||
)
|
||||
)
|
||||
|
|
|
@ -16,7 +16,13 @@ if "%~1"=="clean" (
|
|||
goto exit
|
||||
)
|
||||
|
||||
if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" (
|
||||
set MSYS2Version=20231026
|
||||
|
||||
set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe
|
||||
set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install%
|
||||
set MSYS2UnpackPath=%EnvMSYS2Path%\msys64
|
||||
|
||||
if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" (
|
||||
if "%~1"=="reinstall" (
|
||||
choice /M "Found existing MSYS2 version. Do you want to proceed?"
|
||||
if !ERRORLEVEL!==2 goto exit
|
||||
|
@ -25,29 +31,26 @@ if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" (
|
|||
)
|
||||
)
|
||||
|
||||
if "%MSYS2Architecture%"=="i686" set MSYS2Version=20210705
|
||||
if "%MSYS2Architecture%"=="x86_64" set MSYS2Version=20210725
|
||||
|
||||
set MSYS2Install=msys2-base-%MSYS2Architecture%-%MSYS2Version%.tar.xz
|
||||
set MSYS2Url=https://repo.msys2.org/distrib/%MSYS2Architecture%/%MSYS2Install%
|
||||
|
||||
if exist "%MSYS2UnpackPath%" (
|
||||
%cecho% info "Remove previous MSYS2 version"
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvMSYS2Path%"
|
||||
call "%ToolsPath%\remove-dir.bat" "%MSYS2UnpackPath%"
|
||||
)
|
||||
|
||||
%cecho% info "Download installation files"
|
||||
%cecho% info "Download MSYS2 installation files"
|
||||
if not exist "%EnvDownloadPath%\%MSYS2Install%" call "%ToolsPath%\download-file.bat" "%MSYS2Url%" "%EnvDownloadPath%\%MSYS2Install%"
|
||||
if not exist "%EnvDownloadPath%\%MSYS2Install%" %cecho% error "Cannot download MSYS" & goto error
|
||||
|
||||
%cecho% info "Unpack MSYS2"
|
||||
"%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%MSYS2Install%" | "%EnvSevenZipExe%" x -y -si -ttar -o"%EnvMSYS2Path%"
|
||||
"%EnvDownloadPath%\%MSYS2Install%" -y -o"%EnvMSYS2Path%"
|
||||
|
||||
set MSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh
|
||||
set MSYS2SH=%MSYS2UnpackPath%\usr\bin\sh
|
||||
|
||||
%cecho% info "Initialize MSYS2"
|
||||
"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Sy"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Su"
|
||||
|
||||
call "%EnvMSYS2Path%\msys%MSYS2Base%\autorebase.bat"
|
||||
call "%MSYS2UnpackPath%\autorebase.bat"
|
||||
|
||||
:exit
|
||||
endlocal
|
||||
|
|
|
@ -34,7 +34,7 @@ if not exist "%EnvToolsPath%\cecho.exe" (
|
|||
if not exist "%EnvDownloadPath%\%cCEhoInstall%" echo Cannot download cecho installation& goto error
|
||||
|
||||
echo Unpack cecho
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" -y -bso0
|
||||
copy "%EnvTempPath%\cecho.exe" "%EnvToolsPath%"
|
||||
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
|
||||
setlocal
|
||||
|
||||
if exist "%~dp0msys2\msys32" call :update 32
|
||||
if exist "%~dp0msys2\msys64" call :update 64
|
||||
if not exist "%~dp0msys2\msys64" goto :EOF
|
||||
|
||||
goto :EOF
|
||||
set MSYS2SH=%~dp0msys2\msys64\usr\bin\sh
|
||||
|
||||
:update
|
||||
set MSYS2SH=%~dp0msys2\msys%~1\usr\bin\sh
|
||||
|
||||
echo Update MSYS2 %~1
|
||||
echo Update MSYS2
|
||||
"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Su"
|
||||
|
||||
:exit
|
||||
endlocal
|
||||
goto :EOF
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
setlocal
|
||||
|
||||
echo.
|
||||
echo === webui
|
||||
echo.
|
||||
title Build webui
|
||||
|
||||
if not exist "%RsWebuiPath%" (
|
||||
echo Checking out webui source into %RsWebuiPath%
|
||||
if not "%ParamNoupdate%"=="1" (
|
||||
%EnvMSYS2Cmd% "pacman --noconfirm --needed -S git"
|
||||
)
|
||||
git clone https://github.com/RetroShare/RSNewWebUI.git "%RsWebuiPath%"
|
||||
) else (
|
||||
echo Webui source found at %RsWebuiPath%
|
||||
)
|
||||
|
||||
pushd "%RsWebuiPath%\webui-src\make-src"
|
||||
%EnvMSYS2Cmd% "sh build.sh"
|
||||
popd
|
||||
|
||||
endlocal
|
|
@ -1,18 +1,18 @@
|
|||
ZLIB_VERSION=1.2.3
|
||||
BZIP2_VERSION=1.0.6
|
||||
MINIUPNPC_VERSION=2.0
|
||||
OPENSSL_VERSION=1.1.1h
|
||||
ZLIB_VERSION=1.2.11
|
||||
BZIP2_VERSION=1.0.8
|
||||
MINIUPNPC_VERSION=2.2.3
|
||||
OPENSSL_VERSION=1.1.1w
|
||||
SPEEX_VERSION=1.2.0
|
||||
SPEEXDSP_VERSION=1.2rc3
|
||||
LIBXML2_VERSION=2.9.7
|
||||
LIBXSLT_VERSION=1.1.32
|
||||
CURL_VERSION=7.58.0
|
||||
SPEEXDSP_VERSION=1.2.0
|
||||
LIBXML2_VERSION=2.9.12
|
||||
LIBXSLT_VERSION=1.1.34
|
||||
CURL_VERSION=7.81.0
|
||||
TCL_VERSION=8.6.10
|
||||
SQLCIPHER_VERSION=4.4.0
|
||||
LIBMICROHTTPD_VERSION=0.9.59
|
||||
FFMPEG_VERSION=3.4
|
||||
SQLCIPHER_VERSION=4.5.0
|
||||
LIBMICROHTTPD_VERSION=0.9.75
|
||||
FFMPEG_VERSION=4.4
|
||||
RAPIDJSON_VERSION=1.1.0
|
||||
XAPIAN_VERSION=1.4.7
|
||||
XAPIAN_VERSION=1.4.19
|
||||
|
||||
DOWNLOAD_PATH?=download
|
||||
BUILD_PATH=build
|
||||
|
@ -56,8 +56,7 @@ $(BUILD_PATH)/zlib-$(ZLIB_VERSION): $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz
|
|||
rm -r -f $(BUILD_PATH)/zlib-*
|
||||
tar xvf $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz
|
||||
# build
|
||||
cd zlib-$(ZLIB_VERSION) && ./configure
|
||||
#cd zlib-$(ZLIB_VERSION) && make install prefix="`pwd`/../$(BUILD_PATH)"
|
||||
cd zlib-$(ZLIB_VERSION) && make -f win32/Makefile.gcc libz.a
|
||||
cd zlib-$(ZLIB_VERSION) && make
|
||||
# copy files
|
||||
mkdir -p $(BUILD_PATH)/zlib-$(ZLIB_VERSION).tmp/include
|
||||
|
@ -72,7 +71,7 @@ $(BUILD_PATH)/zlib-$(ZLIB_VERSION): $(DOWNLOAD_PATH)/zlib-$(ZLIB_VERSION).tar.gz
|
|||
bzip2: $(BUILD_PATH)/bzip2-$(BZIP2_VERSION)
|
||||
|
||||
$(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz:
|
||||
wget https://sourceforge.net/projects/bzip2/files/bzip2-$(BZIP2_VERSION).tar.gz/download -O $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz
|
||||
wget https://www.sourceware.org/pub/bzip2/bzip2-$(BZIP2_VERSION).tar.gz -O $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz
|
||||
|
||||
$(BUILD_PATH)/bzip2-$(BZIP2_VERSION): $(DOWNLOAD_PATH)/bzip2-$(BZIP2_VERSION).tar.gz
|
||||
# prepare
|
||||
|
@ -100,10 +99,10 @@ $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION): $(DOWNLOAD_PATH)/miniupnpc-$(MINIU
|
|||
rm -r -f $(BUILD_PATH)/miniupnpc-*
|
||||
tar xvf $(DOWNLOAD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tar.gz
|
||||
# build
|
||||
cd miniupnpc-$(MINIUPNPC_VERSION) && export CC=gcc && export PATH=.:$$PATH && make -f Makefile.mingw init libminiupnpc.a miniupnpc.dll
|
||||
cd miniupnpc-$(MINIUPNPC_VERSION) && export CC=gcc && export PATH=.:$$PATH && make -f Makefile.mingw libminiupnpc.a miniupnpc.dll
|
||||
# copy files
|
||||
mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc
|
||||
cp miniupnpc-$(MINIUPNPC_VERSION)/*.h $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc/
|
||||
cp miniupnpc-$(MINIUPNPC_VERSION)/include/*.h $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/include/miniupnpc/
|
||||
mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/lib
|
||||
cp miniupnpc-$(MINIUPNPC_VERSION)/miniupnpc.lib $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/lib/
|
||||
mkdir -p $(BUILD_PATH)/miniupnpc-$(MINIUPNPC_VERSION).tmp/bin
|
||||
|
@ -314,7 +313,7 @@ $(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION): $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION
|
|||
rm -r -f $(BUILD_PATH)/ffmpeg-*
|
||||
tar xvf $(DOWNLOAD_PATH)/ffmpeg-$(FFMPEG_VERSION).tar.gz
|
||||
# build
|
||||
cd ffmpeg-$(FFMPEG_VERSION) && ./configure --disable-shared --enable-static --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-yasm --disable-everything --enable-encoder=mpeg4 --enable-decoder=mpeg4 --prefix="`pwd`/../$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION).tmp"
|
||||
cd ffmpeg-$(FFMPEG_VERSION) && ./configure --disable-shared --enable-static --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-yasm --disable-everything --enable-encoder=mpeg4 --enable-decoder=mpeg4 --prefix="`pwd`/../$(BUILD_PATH)/ffmpeg-$(FFMPEG_VERSION).tmp"
|
||||
cd ffmpeg-$(FFMPEG_VERSION) && make install
|
||||
# cleanup
|
||||
rm -r -f ffmpeg-$(FFMPEG_VERSION)
|
||||
|
|
|
@ -13,11 +13,11 @@ call "%~dp0build-libs\build-libs.bat"
|
|||
if errorlevel 1 %cecho% error "Failed to build libraries." & exit /B %ERRORLEVEL%
|
||||
|
||||
%cecho% info "Build %SourceName%"
|
||||
call "%~dp0build\build.bat" release autologin jsonapi plugins nativedialogs
|
||||
call "%~dp0build\build.bat" release autologin webui plugins nativedialogs service
|
||||
if errorlevel 1 %cecho% error "Failed to build %SourceName%." & exit /B %ERRORLEVEL%
|
||||
|
||||
%cecho% info "Pack %SourceName%"
|
||||
call "%~dp0build\pack.bat" release plugins
|
||||
call "%~dp0build\pack.bat" release webui plugins service
|
||||
if errorlevel 1 %cecho% error "Failed to pack %SourceName%." & exit /B %ERRORLEVEL%
|
||||
|
||||
%cecho% info "Build installer"
|
||||
|
|
|
@ -9,7 +9,7 @@ call "%EnvPath%\env.bat"
|
|||
if errorlevel 1 goto error_env
|
||||
|
||||
:: Initialize environment
|
||||
call "%~dp0env.bat" release
|
||||
call "%~dp0env.bat" installer release
|
||||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
|
@ -40,6 +40,7 @@ set NSIS_PARAM=%NSIS_PARAM% /DARCHITECTURE="%GCCArchitecture%"
|
|||
set NSIS_PARAM=%NSIS_PARAM% /DDATE="%RsDate%"
|
||||
|
||||
if exist "%EnvTorPath%\Tor\tor.exe" set NSIS_PARAM=%NSIS_PARAM% /DTORDIR="%EnvTorPath%\Tor"
|
||||
if exist "%RsWebuiBuildPath%" set NSIS_PARAM=%NSIS_PARAM% /DWEBUIDIR="%RsWebuiBuildPath%"
|
||||
|
||||
:: Get compiled version
|
||||
call "%ToolsPath%\get-rs-version.bat" "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare.exe" RsVersion
|
||||
|
|
|
@ -9,7 +9,7 @@ call "%EnvPath%\env.bat"
|
|||
if errorlevel 1 goto error_env
|
||||
|
||||
:: Initialize environment
|
||||
call "%~dp0env.bat" %*
|
||||
call "%~dp0env.bat" build %*
|
||||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
|
@ -49,11 +49,15 @@ echo.
|
|||
|
||||
title Build - %SourceName%-%RsBuildConfig% [qmake]
|
||||
|
||||
set RS_QMAKE_CONFIG=%RsBuildConfig% no_rs_cppwarning
|
||||
set RS_QMAKE_CONFIG=%RsBuildConfig%
|
||||
if "%ParamAutologin%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_autologin
|
||||
if "%ParamJsonApi%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_jsonapi
|
||||
if "%ParamWebui%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_webui
|
||||
if "%ParamPlugins%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% retroshare_plugins
|
||||
if "%ParamUseNativeDialogs%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_use_native_dialogs
|
||||
if "%ParamService%" NEQ "1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% no_retroshare_service
|
||||
if "%ParamFriendServer%" NEQ "1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% no_retroshare_friendserver
|
||||
if "%ParamEmbeddedFriendServer%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% rs_efs
|
||||
|
||||
qmake "%SourcePath%\RetroShare.pro" -r -spec win32-g++ "CONFIG+=%RS_QMAKE_CONFIG%" "EXTERNAL_LIB_DIR=%BuildLibsPath%\libs"
|
||||
if errorlevel 1 goto error
|
||||
|
|
|
@ -8,7 +8,7 @@ if errorlevel 1 goto error_env
|
|||
call "%EnvPath%\env.bat"
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
call "%~dp0env.bat" %*
|
||||
call "%~dp0env.bat" clean %*
|
||||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
|
|
|
@ -4,11 +4,18 @@ set ParamDebug=0
|
|||
set ParamAutologin=0
|
||||
set ParamPlugins=0
|
||||
set ParamJsonApi=0
|
||||
set ParamWebui=0
|
||||
set ParamService=0
|
||||
set ParamFriendServer=0
|
||||
set ParamEmbeddedFriendServer=0
|
||||
set ParamUseNativeDialogs=0
|
||||
set ParamTor=0
|
||||
set NonInteractive=0
|
||||
set CoreCount=%NUMBER_OF_PROCESSORS%
|
||||
|
||||
set Module=%~1
|
||||
shift /1
|
||||
|
||||
:parameter_loop
|
||||
if "%~1" NEQ "" (
|
||||
for /f "tokens=1,2 delims==" %%a in ("%~1") do (
|
||||
|
@ -20,6 +27,15 @@ if "%~1" NEQ "" (
|
|||
set ParamAutologin=1
|
||||
) else if "%%~a"=="jsonapi" (
|
||||
set ParamJsonApi=1
|
||||
) else if "%%~a"=="webui" (
|
||||
set ParamJsonApi=1
|
||||
set ParamWebui=1
|
||||
) else if "%%~a"=="service" (
|
||||
set ParamService=1
|
||||
) else if "%%~a"=="friendserver" (
|
||||
set ParamFriendServer=1
|
||||
) else if "%%~a"=="embedded-friendserver" (
|
||||
set ParamEmbeddedFriendServer=1
|
||||
) else if "%%~a"=="plugins" (
|
||||
set ParamPlugins=1
|
||||
) else if "%%~a"=="tor" (
|
||||
|
@ -32,7 +48,7 @@ if "%~1" NEQ "" (
|
|||
set ParamUseNativeDialogs=1
|
||||
) else (
|
||||
echo.
|
||||
echo Unknown parameter %1
|
||||
echo Unknown parameter %1 for %Module%
|
||||
goto :usage
|
||||
)
|
||||
)
|
||||
|
@ -89,6 +105,7 @@ set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%GCCArchitecture%-%RsBuildConfig%
|
|||
set RsDeployPath=%DeployPath%\Qt-%QtVersion%-%GCCArchitecture%%RsType%-%RsBuildConfig%
|
||||
set RsPackPath=%DeployPath%
|
||||
set RsArchiveAdd=
|
||||
set RsWebuiBuildPath=%RsBuildPath%\retroshare-webui\webui
|
||||
|
||||
if not exist "%~dp0env-mod.bat" goto no_mod
|
||||
call "%~dp0env-mod.bat"
|
||||
|
@ -104,19 +121,31 @@ echo.
|
|||
echo Mandatory parameter
|
||||
echo release^|debug Build release or debug version
|
||||
echo.
|
||||
echo Optional parameter (need clean when changed)
|
||||
if "%Module%"=="build" (
|
||||
echo Optional parameter ^(need clean when changed^)
|
||||
echo autologin Build with autologin
|
||||
echo jsonapi Build with jsonapi
|
||||
echo webui Build with jsonapi and webui
|
||||
echo service Build service
|
||||
echo friendserver Build Friend Server
|
||||
echo embedded-friendserver Build with embedded Friend Server
|
||||
echo plugins Build plugins
|
||||
echo nativedialogs Build with native dialogs
|
||||
echo.
|
||||
echo Optional parameter
|
||||
echo singlethread Use only 1 thread for building
|
||||
echo.
|
||||
echo Parameter for pack
|
||||
echo tor Pack tor version
|
||||
echo.
|
||||
echo Parameter for git-log
|
||||
)
|
||||
if "%Module%"=="pack" (
|
||||
echo Optional parameter
|
||||
echo webui Pack webui
|
||||
echo service Pack service
|
||||
echo friendserver Pack Friend Server ^(needs Tor^)
|
||||
echo tor Pack Tor version
|
||||
echo plugins Pack plugins
|
||||
)
|
||||
if "%Module%"=="git-log" (
|
||||
echo Optional parameter
|
||||
echo non-interactive Non-interactive mode
|
||||
)
|
||||
echo.
|
||||
exit /B 2
|
||||
|
|
|
@ -8,7 +8,7 @@ if errorlevel 1 goto error_env
|
|||
call "%EnvPath%\env.bat"
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
call "%~dp0env.bat" %*
|
||||
call "%~dp0env.bat" git-log %*
|
||||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
|
@ -88,6 +88,10 @@ echo %RsRef%>"%RsLastRefFile%"
|
|||
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:error
|
||||
%cecho% error "\n%~n0 failed\n"
|
||||
exit /B 1
|
||||
|
||||
:error_env
|
||||
echo Failed to initialize environment.
|
||||
endlocal
|
||||
|
|
|
@ -11,7 +11,7 @@ call "%EnvPath%\env.bat"
|
|||
if errorlevel 1 goto error_env
|
||||
|
||||
:: Initialize environment
|
||||
call "%~dp0env.bat" %*
|
||||
call "%~dp0env.bat" pack %*
|
||||
if errorlevel 2 exit /B 2
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
|
@ -95,9 +95,23 @@ copy nul "%RsDeployPath%\portable" %Quite%
|
|||
|
||||
echo copy binaries
|
||||
copy "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\retroshare*.exe" "%RsDeployPath%" %Quite%
|
||||
copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite%
|
||||
if exist "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" copy "%RsBuildPath%\libretroshare\src\lib\retroshare.dll" "%RsDeployPath%" %Quite%
|
||||
|
||||
if "%ParamService%"=="1" (
|
||||
copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite%
|
||||
if errorlevel 1 %cecho% error "Service not found"& goto error
|
||||
)
|
||||
|
||||
if "%ParamFriendServer%"=="1" (
|
||||
if "%ParamTor%"=="1" (
|
||||
copy "%RsBuildPath%\retroshare-friendserver\src\%RsBuildConfig%\retroshare-friendserver.exe" "%RsDeployPath%" %Quite%
|
||||
if errorlevel 1 %cecho% error "Friend Server not found"& goto error
|
||||
) else (
|
||||
%cecho% error "Friend Server needs Tor"
|
||||
goto error
|
||||
)
|
||||
)
|
||||
|
||||
echo copy extensions
|
||||
if "%ParamPlugins%"=="1" (
|
||||
for /D %%D in ("%RsBuildPath%\plugins\*") do (
|
||||
|
@ -167,10 +181,11 @@ copy "%SourcePath%\libbitdht\src\bitdht\bdboot.txt" "%RsDeployPath%" %Quite%
|
|||
echo copy changelog.txt
|
||||
copy "%RsBuildPath%\changelog.txt" "%RsDeployPath%" %Quite%
|
||||
|
||||
if exist "%SourcePath%\libresapi\src\webui" (
|
||||
if defined ParamWebui (
|
||||
echo copy webui
|
||||
mkdir "%RsDeployPath%\webui"
|
||||
xcopy /S "%SourcePath%\libresapi\src\webui" "%RsDeployPath%\webui" %Quite%
|
||||
xcopy /S "%RsWebuiBuildPath%" "%RsDeployPath%\webui" %Quite%
|
||||
if errorlevel 1 %cecho% error "WebUi not found"& goto error
|
||||
)
|
||||
|
||||
if "%ParamTor%"=="1" (
|
||||
|
|
4
build_scripts/Windows/env/env-msys2.bat
vendored
4
build_scripts/Windows/env/env-msys2.bat
vendored
|
@ -5,7 +5,6 @@
|
|||
call "%~dp0env.bat"
|
||||
if errorlevel 1 goto error_env
|
||||
|
||||
rem openssl x86 doesn't compile with mingw64 x64
|
||||
:: Get gcc versions
|
||||
call "%ToolsPath%\get-gcc-version.bat" GCCVersion GCCArchitecture
|
||||
if "%GCCVersion%"=="" %cecho% error "Cannot get gcc version." & exit /B 1
|
||||
|
@ -23,11 +22,12 @@ if "%GCCArchitecture%"=="x64" (
|
|||
)
|
||||
|
||||
set EnvMSYS2Path=%EnvRootPath%\msys2
|
||||
set EnvMSYS2BasePath=%EnvMSYS2Path%\msys64
|
||||
|
||||
call "%~dp0tools\prepare-msys2.bat" %1
|
||||
if errorlevel 1 exit /B %ERRORLEVEL%
|
||||
|
||||
set EnvMSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh.exe
|
||||
set EnvMSYS2SH=%EnvMSYS2BasePath%\usr\bin\sh.exe
|
||||
if not exist "%EnvMSYS2SH%" if errorlevel 1 goto error_env
|
||||
|
||||
set EnvMSYS2Cmd="%EnvMSYS2SH%" -lc
|
||||
|
|
3
build_scripts/Windows/env/env.bat
vendored
3
build_scripts/Windows/env/env.bat
vendored
|
@ -28,6 +28,9 @@ if errorlevel 1 exit /B %ERRORLEVEL%
|
|||
set PATH=%EnvToolsPath%\MinGit\cmd;%EnvToolsPath%\cmake\bin;%PATH%
|
||||
set HOME=%EnvToolsPath%\MinGit\home
|
||||
|
||||
:: Add Doxygen to PATH
|
||||
set PATH=%EnvToolsPath%\doxygen;%PATH%
|
||||
|
||||
exit /B 0
|
||||
|
||||
:error_env
|
||||
|
|
|
@ -16,7 +16,15 @@ if "%~1"=="clean" (
|
|||
goto exit
|
||||
)
|
||||
|
||||
if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" (
|
||||
set MSYS2Version=20231026
|
||||
|
||||
set MSYS2Install=msys2-base-x86_64-%MSYS2Version%.sfx.exe
|
||||
set MSYS2Url=https://github.com/msys2/msys2-installer/releases/download/%MSYS2Version:~0,4%-%MSYS2Version:~4,2%-%MSYS2Version:~6,2%/%MSYS2Install%
|
||||
set MSYS2UnpackPath=%EnvMSYS2Path%\msys64
|
||||
set CMakeInstall=cmake-3.19.0-win32-x86.zip
|
||||
set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall%
|
||||
|
||||
if exist "%MSYS2UnpackPath%\usr\bin\pacman.exe" (
|
||||
if "%~1"=="reinstall" (
|
||||
choice /M "Found existing MSYS2 version. Do you want to proceed?"
|
||||
if !ERRORLEVEL!==2 goto exit
|
||||
|
@ -25,21 +33,12 @@ if exist "%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\pacman.exe" (
|
|||
)
|
||||
)
|
||||
|
||||
if "%MSYS2Architecture%"=="i686" set MSYS2Version=20210705
|
||||
if "%MSYS2Architecture%"=="x86_64" set MSYS2Version=20210725
|
||||
|
||||
set MSYS2Install=msys2-base-%MSYS2Architecture%-%MSYS2Version%.tar.xz
|
||||
set MSYS2Url=https://repo.msys2.org/distrib/%MSYS2Architecture%/%MSYS2Install%
|
||||
set CMakeInstall=cmake-3.19.0-win32-x86.zip
|
||||
set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall%
|
||||
set CMakeUnpackPath=%EnvMSYS2Path%\msys%MSYS2Base%
|
||||
|
||||
if exist "%EnvMSYS2Path%\msys%MSYS2Base%" (
|
||||
if exist "%MSYS2UnpackPath%" (
|
||||
%cecho% info "Remove previous MSYS2 version"
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvMSYS2Path%\msys%MSYS2Base%"
|
||||
call "%ToolsPath%\remove-dir.bat" "%MSYS2UnpackPath%"
|
||||
)
|
||||
|
||||
%cecho% info "Download installation files"
|
||||
%cecho% info "Download MSYS2 installation files"
|
||||
if not exist "%EnvDownloadPath%\%MSYS2Install%" call "%ToolsPath%\download-file.bat" "%MSYS2Url%" "%EnvDownloadPath%\%MSYS2Install%"
|
||||
if not exist "%EnvDownloadPath%\%MSYS2Install%" %cecho% error "Cannot download MSYS" & goto error
|
||||
|
||||
|
@ -47,31 +46,32 @@ if not exist "%EnvDownloadPath%\%CMakeInstall%" call "%ToolsPath%\download-file.
|
|||
if not exist "%EnvDownloadPath%\%CMakeInstall%" %cecho% error "Cannot download CMake" & goto error
|
||||
|
||||
%cecho% info "Unpack MSYS2"
|
||||
"%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%MSYS2Install%" | "%EnvSevenZipExe%" x -y -si -ttar -o"%EnvMSYS2Path%"
|
||||
"%EnvDownloadPath%\%MSYS2Install%" -y -o"%EnvMSYS2Path%"
|
||||
|
||||
%cecho% info "Unpack CMake"
|
||||
"%EnvSevenZipExe%" x -o"%CMakeUnpackPath%" "%EnvDownloadPath%\%CMakeInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%MSYS2UnpackPath%" "%EnvDownloadPath%\%CMakeInstall%" -y -bso0
|
||||
|
||||
%cecho% info "Install CMake"
|
||||
set CMakeVersion=
|
||||
for /D %%F in (%CMakeUnpackPath%\cmake*) do set CMakeVersion=%%~nxF
|
||||
for /D %%F in (%MSYS2UnpackPath%\cmake*) do set CMakeVersion=%%~nxF
|
||||
if "%CMakeVersion%"=="" %cecho% error "CMake version not found." & goto :exit
|
||||
%cecho% info "Found CMake version %CMakeVersion%"
|
||||
|
||||
set FoundProfile=
|
||||
for /f "tokens=3" %%F in ('find /c /i "%CMakeVersion%" "%EnvMSYS2Path%\msys%MSYS2Base%\etc\profile"') do set FoundProfile=%%F
|
||||
for /f "tokens=3" %%F in ('find /c /i "%CMakeVersion%" "%MSYS2UnpackPath%\etc\profile"') do set FoundProfile=%%F
|
||||
|
||||
if "%FoundProfile%"=="0" (
|
||||
echo export PATH="${PATH}:/%CMakeVersion%/bin">>"%EnvMSYS2Path%\msys%MSYS2Base%\etc\profile"
|
||||
echo export PATH="${PATH}:/%CMakeVersion%/bin">>"%MSYS2UnpackPath%\etc\profile"
|
||||
)
|
||||
|
||||
set MSYS2SH=%EnvMSYS2Path%\msys%MSYS2Base%\usr\bin\sh
|
||||
set MSYS2SH=%MSYS2UnpackPath%\usr\bin\sh
|
||||
|
||||
%cecho% info "Initialize MSYS2"
|
||||
"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Sy"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Su"
|
||||
|
||||
call "%EnvMSYS2Path%\msys%MSYS2Base%\autorebase.bat"
|
||||
call "%MSYS2UnpackPath%\autorebase.bat"
|
||||
|
||||
:exit
|
||||
endlocal
|
||||
|
|
|
@ -16,6 +16,9 @@ set NSISInstallPath=%EnvToolsPath%\NSIS
|
|||
set MinGitInstall=MinGit-2.28.0-32-bit.zip
|
||||
set MinGitUrl=https://github.com/git-for-windows/git/releases/download/v2.28.0.windows.1/%MinGitInstall%
|
||||
set MinGitInstallPath=%EnvToolsPath%\MinGit
|
||||
set DoxygenInstall=doxygen-1.9.6.windows.x64.bin.zip
|
||||
set DoxygenUrl=https://github.com/doxygen/doxygen/releases/download/Release_1_9_6/%DoxygenInstall%
|
||||
set DoxygenInstallPath=%EnvToolsPath%\doxygen
|
||||
set CMakeVersion=cmake-3.19.0-win32-x86
|
||||
set CMakeInstall=%CMakeVersion%.zip
|
||||
set CMakeUrl=https://github.com/Kitware/CMake/releases/download/v3.19.0/%CMakeInstall%
|
||||
|
@ -50,7 +53,7 @@ if not exist "%EnvToolsPath%\cecho.exe" (
|
|||
if not exist "%EnvDownloadPath%\%cCEhoInstall%" echo Cannot download cecho installation& goto error
|
||||
|
||||
echo Unpack cecho
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CEchoInstall%" -y -bso0
|
||||
copy "%EnvTempPath%\cecho.exe" "%EnvToolsPath%"
|
||||
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
|
@ -66,7 +69,7 @@ if not exist "%EnvToolsPath%\depends.exe" (
|
|||
if not exist "%EnvDownloadPath%\%DependsInstall%" %cecho% error "Cannot download Dependendy Walker installation" & goto error
|
||||
|
||||
%cecho% info "Unpack Dependency Walker"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%DependsInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%DependsInstall%" -y -bso0
|
||||
copy "%EnvTempPath%\*" "%EnvToolsPath%"
|
||||
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
|
@ -82,7 +85,7 @@ if not exist "%EnvToolsPath%\cut.exe" (
|
|||
if not exist "%EnvDownloadPath%\%UnixToolsInstall%" %cecho% error "Cannot download Unix Tools installation" & goto error
|
||||
|
||||
%cecho% info "Unpack Unix Tools"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" -y -bso0
|
||||
copy "%EnvTempPath%\cut.exe" "%EnvToolsPath%"
|
||||
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
|
@ -98,7 +101,7 @@ if not exist "%EnvToolsPath%\sed.exe" (
|
|||
if not exist "%EnvDownloadPath%\%UnixToolsInstall%" %cecho% error "Cannot download Unix Tools installation" & goto error
|
||||
|
||||
%cecho% info "Unpack Unix Tools"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%UnixToolsInstall%" -y -bso0
|
||||
copy "%EnvTempPath%\sed.exe" "%EnvToolsPath%"
|
||||
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
|
@ -118,7 +121,7 @@ if not exist "%NSISInstallPath%\nsis.exe" (
|
|||
if not exist "%EnvDownloadPath%\%NSISInstall%" %cecho% error "Cannot download NSIS installation" & goto error
|
||||
|
||||
%cecho% info "Unpack NSIS"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%NSISInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%NSISInstall%" -y -bso0
|
||||
if not exist "%NSISInstallPath%" mkdir "%NSISInstallPath%"
|
||||
xcopy /s "%EnvTempPath%" "%NSISInstallPath%"
|
||||
|
||||
|
@ -132,7 +135,20 @@ if not exist "%MinGitInstallPath%\cmd\git.exe" (
|
|||
if not exist "%EnvDownloadPath%\%MinGitInstall%" %cecho% error "Cannot download MinGit installation" & goto error
|
||||
|
||||
%cecho% info "Unpack MinGit"
|
||||
"%EnvSevenZipExe%" x -o"%MinGitInstallPath%" "%EnvDownloadPath%\%MinGitInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%MinGitInstallPath%" "%EnvDownloadPath%\%MinGitInstall%" -y -bso0
|
||||
)
|
||||
|
||||
if not exist "%EnvDownloadPath%\%DoxygenInstall%" call "%ToolsPath%\remove-dir.bat" "%DoxygenInstallPath%"
|
||||
if not exist "%DoxygenInstallPath%\doxygen.exe" (
|
||||
if exist "%DoxygenInstallPath%" call "%ToolsPath%\remove-dir.bat" "%DoxygenInstallPath%"
|
||||
|
||||
%cecho% info "Download Doxygen installation"
|
||||
|
||||
if not exist "%EnvDownloadPath%\%DoxygenInstall%" call "%ToolsPath%\download-file.bat" "%DoxygenUrl%" "%EnvDownloadPath%\%DoxygenInstall%"
|
||||
if not exist "%EnvDownloadPath%\%DoxygenInstall%" %cecho% error "Cannot download doxygen installation" & goto error
|
||||
|
||||
%cecho% info "Unpack Doxygen"
|
||||
"%EnvSevenZipExe%" x -o"%DoxygenInstallPath%" "%EnvDownloadPath%\%DoxygenInstall%" -y -bso0
|
||||
)
|
||||
|
||||
if not exist "%EnvDownloadPath%\%CMakeInstall%" call "%ToolsPath%\remove-dir.bat" "%CMakeInstallPath%"
|
||||
|
@ -147,7 +163,7 @@ if not exist "%CMakeInstallPath%\bin\cmake.exe" (
|
|||
if not exist "%EnvDownloadPath%\%CMakeInstall%" %cecho% error "Cannot download CMake installation" & goto error
|
||||
|
||||
%cecho% info "Unpack CMake"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CMakeInstall%"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%CMakeInstall%" -y -bso0
|
||||
|
||||
move "%EnvTempPath%\%CMakeVersion%" "%CMakeInstallPath%"
|
||||
|
||||
|
@ -160,7 +176,7 @@ mkdir "%EnvTempPath%"
|
|||
call "%ToolsPath%\download-file.bat" "%TorDownloadIndexUrl%" "%EnvTempPath%\index.html"
|
||||
if not exist "%EnvTempPath%\index.html" %cecho% error "Cannot download Tor installation" & goto error
|
||||
|
||||
for /F "tokens=1,2 delims= " %%A in ('%EnvSedExe% -r -n -e"s/.*href=\"^(.*^)^(tor-win32.*\.zip^)\".*/\2 \1\2/p" "%EnvTempPath%\index.html"') do set TorInstall=%%A& set TorDownloadUrl=%TorProjectUrl%%%B
|
||||
for /F "tokens=1,2 delims= " %%A in ('%EnvSedExe% -r -n -e"s/.*href=\"^(.*^)^(tor-.*windows-i686.*\.tar\.gz^)\".*/\2 \1\2/p" "%EnvTempPath%\index.html"') do set TorInstall=%%A& set TorDownloadUrl=%%B
|
||||
call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%"
|
||||
if "%TorInstall%"=="" %cecho% error "Cannot download Tor installation" & goto error
|
||||
if "%TorDownloadUrl%"=="" %cecho% error "Cannot download Tor installation" & goto error
|
||||
|
@ -173,7 +189,7 @@ if not exist "%EnvTorPath%\Tor\tor.exe" (
|
|||
if not exist "%EnvDownloadPath%\%TorInstall%" %cecho% error "Cannot download Tor installation" & goto error
|
||||
|
||||
%cecho% info "Unpack Tor"
|
||||
"%EnvSevenZipExe%" x -o"%EnvTorPath%" "%EnvDownloadPath%\%TorInstall%"
|
||||
"%EnvSevenZipExe%" x -so "%EnvDownloadPath%\%TorInstall%" | "%EnvSevenZipExe%" x -si -ttar -o"%EnvTorPath%" -y -bso0
|
||||
)
|
||||
|
||||
:exit
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
|
||||
setlocal
|
||||
|
||||
if exist "%~dp0msys2\msys32" call :update 32
|
||||
if exist "%~dp0msys2\msys64" call :update 64
|
||||
if not exist "%~dp0msys2\msys64" goto :EOF
|
||||
|
||||
goto :EOF
|
||||
set MSYS2SH=%~dp0msys2\msys64\usr\bin\sh
|
||||
|
||||
:update
|
||||
set MSYS2SH=%~dp0msys2\msys%~1\usr\bin\sh
|
||||
|
||||
echo Update MSYS2 %~1
|
||||
echo Update MSYS2
|
||||
"%MSYS2SH%" -lc "yes | pacman --noconfirm -Syuu msys2-keyring"
|
||||
"%MSYS2SH%" -lc "pacman --noconfirm -Su"
|
||||
|
||||
:exit
|
||||
endlocal
|
||||
goto :EOF
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Instal·la ${APPNAME} i els components necessaris."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Pells"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Instal·la pells."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Icones d'accés directe"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Installiert ${APPNAME} und die benötigten Komponenten."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installiert Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installiert WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installiert Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installiert Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Skins"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Skins installieren."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Verknüpfungssymbole"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Installs ${APPNAME} and required components."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Skins"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Installs skins."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Shortcut icons"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Instala ${APPNAME} y los componentes requeridos."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Coberturas (skins)"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Instalar coberturas"
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Iconos de accesos directos"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Installe ${APPNAME} et les composants requis."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Habillages"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Installe des habillages."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Icônes de raccourci"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Instaluje ${APPNAME} oraz wymagane komponenty."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Skórki"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Instaluje skórki."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Ikony skrótów"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Установка ${APPNAME} и необходимых компонентов."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Оболочки"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Установка оболочек."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Ярлыки"
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "${APPNAME} ve gerekli bileşenleri kurar."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "Temalar"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "Tema yükleyin."
|
||||
!insertmacro LANG_STRING Section_Shortcuts "Kısayol simgeleri"
|
||||
|
|
|
@ -22,6 +22,48 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_WebUI</name>
|
||||
<message>
|
||||
<source>WebUI</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_WebUI_Desc</name>
|
||||
<message>
|
||||
<source>Installs WebUI.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_Service</name>
|
||||
<message>
|
||||
<source>Service</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_Service_Desc</name>
|
||||
<message>
|
||||
<source>Installs Service.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_FriendServer</name>
|
||||
<message>
|
||||
<source>Friend Server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_FriendServer_Desc</name>
|
||||
<message>
|
||||
<source>Installs Friend Server.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Section_Data</name>
|
||||
<message>
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
!insertmacro LANG_STRING Section_Main_Desc "Installs ${APPNAME} and required components."
|
||||
!insertmacro LANG_STRING Section_Tor "Tor"
|
||||
!insertmacro LANG_STRING Section_Tor_Desc "Installs Tor."
|
||||
!insertmacro LANG_STRING Section_WebUI "WebUI"
|
||||
!insertmacro LANG_STRING Section_WebUI_Desc "Installs WebUI."
|
||||
!insertmacro LANG_STRING Section_Service "Service"
|
||||
!insertmacro LANG_STRING Section_Service_Desc "Installs Service."
|
||||
!insertmacro LANG_STRING Section_FriendServer "Friend Server"
|
||||
!insertmacro LANG_STRING Section_FriendServer_Desc "Installs Friend Server."
|
||||
!insertmacro LANG_STRING Section_Data "皮肤"
|
||||
!insertmacro LANG_STRING Section_Data_Desc "安装皮肤"
|
||||
!insertmacro LANG_STRING Section_Shortcuts "快捷方式图标"
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
!define /date DATE "%Y%m%d"
|
||||
!endif
|
||||
|
||||
# Service
|
||||
${!defineifexist} SERVICE_EXISTS "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe"
|
||||
|
||||
# Tor
|
||||
!ifdef TORDIR
|
||||
${!defineifexist} TOR_EXISTS "${TORDIR}\tor.exe"
|
||||
|
@ -68,6 +71,20 @@ ${!defineifexist} TOR_EXISTS "${TORDIR}\tor.exe"
|
|||
!endif
|
||||
!endif
|
||||
|
||||
# WebUI
|
||||
!ifdef WEBUIDIR
|
||||
${!defineifexist} WEBUI_EXISTS "${WEBUIDIR}\index.html"
|
||||
!ifndef WEBUI_EXISTS
|
||||
!error "WebUI files not found"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
# Friend Server
|
||||
!ifdef TOR_EXISTS
|
||||
# Add Friend Server with Tor only
|
||||
#${!defineifexist} FRIENDSERVER_EXISTS "${RELEASEDIR}\retroshare-friendserver\src\release\retroshare-friendserver.exe"
|
||||
!endif
|
||||
|
||||
# Application name and version
|
||||
!define APPNAME "RetroShare"
|
||||
!define APPNAMEANDVERSION "${APPNAME} ${VERSION}"
|
||||
|
@ -193,7 +210,6 @@ Section $(Section_Main) Section_Main
|
|||
; Main binaries
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${RELEASEDIR}\retroshare-gui\src\release\retroshare.exe"
|
||||
File "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe"
|
||||
File /nonfatal "${RELEASEDIR}\libretroshare\src\lib\retroshare.dll"
|
||||
|
||||
; Qt binaries
|
||||
|
@ -282,11 +298,35 @@ Section $(Section_Main) Section_Main
|
|||
File /r "${SOURCEDIR}\retroshare-gui\src\license\*.*"
|
||||
SectionEnd
|
||||
|
||||
# Service
|
||||
!ifdef SERVICE_EXISTS
|
||||
Section /o $(Section_Service) Section_Service
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${RELEASEDIR}\retroshare-service\src\release\retroshare-service.exe"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
# Friend Server
|
||||
!ifdef FRIENDSERVER_EXISTS
|
||||
Section /o $(Section_FriendServer) Section_FriendServer
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${RELEASEDIR}\retroshare-friendserver\src\release\retroshare-friendserver.exe"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
# Tor
|
||||
!ifdef TOR_EXISTS
|
||||
Section /o $(Section_Tor) Section_Tor
|
||||
SetOutPath "$INSTDIR\tor"
|
||||
File /r "${TORDIR}\*"
|
||||
File "${TORDIR}\*"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
# WebUI
|
||||
!ifdef WEBUI_EXISTS
|
||||
Section /o $(Section_WebUI) Section_WebUI
|
||||
SetOutPath "$INSTDIR\webui"
|
||||
File /r "${WEBUIDIR}\*"
|
||||
SectionEnd
|
||||
!endif
|
||||
|
||||
|
@ -355,6 +395,22 @@ Section $(Section_StartMenu) Section_StartMenu
|
|||
CreateDirectory "$SMPROGRAMS\${APPNAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\$(Link_Uninstall).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\retroshare.exe" "" "$INSTDIR\retroshare.exe" 0
|
||||
|
||||
!ifdef SERVICE_EXISTS
|
||||
SectionGetFlags ${Section_Service} $0
|
||||
IntOp $0 $0 & ${SF_SELECTED}
|
||||
${If} $0 == ${SF_SELECTED}
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME} Service.lnk" "$INSTDIR\retroshare-service.exe" "" "$INSTDIR\retroshare-service.exe" 0
|
||||
${EndIf}
|
||||
!endif
|
||||
|
||||
!ifdef FRIENDSERVER_EXISTS
|
||||
SectionGetFlags ${Section_FriendServer} $0
|
||||
IntOp $0 $0 & ${SF_SELECTED}
|
||||
${If} $0 == ${SF_SELECTED}
|
||||
CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME} Friend Server.lnk" "$INSTDIR\retroshare-friendserver.exe" "" "$INSTDIR\retroshare-friendserver.exe" 0
|
||||
${EndIf}
|
||||
!endif
|
||||
SectionEnd
|
||||
|
||||
Section $(Section_Desktop) Section_Desktop
|
||||
|
@ -407,6 +463,9 @@ SectionEnd
|
|||
; !insertmacro MUI_DESCRIPTION_TEXT ${Section_Link} $(Section_Link_Desc)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${Section_AutoStart} $(Section_AutoStart_Desc)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${Section_Tor} $(Section_Tor_Desc)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${Section_WebUI} $(Section_WebUI_Desc)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${Section_Service} $(Section_Service_Desc)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${Section_FriendServer} $(Section_FriendServer_Desc)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
||||
# Uninstall
|
||||
|
@ -461,6 +520,26 @@ Function .onInit
|
|||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
FunctionEnd
|
||||
|
||||
!ifdef FRIENDSERVER_EXISTS
|
||||
Function .onSelChange
|
||||
SectionGetFlags ${Section_FriendServer} $0
|
||||
IntOp $0 $0 & ${SF_SELECTED}
|
||||
${If} $0 == ${SF_SELECTED}
|
||||
# Activate Tor and set readonly
|
||||
SectionGetFlags ${Section_Tor} $1
|
||||
IntOp $1 $1 | ${SF_SELECTED}
|
||||
IntOp $1 $1 | ${SF_RO}
|
||||
SectionSetFlags ${Section_Tor} $1
|
||||
${Else}
|
||||
# Remove readonly from Tor
|
||||
SectionGetFlags ${Section_Tor} $1
|
||||
IntOp $2 ${SF_RO} ~
|
||||
IntOp $1 $1 & $2
|
||||
SectionSetFlags ${Section_Tor} $1
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
!endif
|
||||
|
||||
# Installation mode
|
||||
|
||||
Function RequireAdmin
|
||||
|
|
|
@ -18,6 +18,8 @@ copy nul %logfile% > nul
|
|||
|
||||
pushd %~1
|
||||
|
||||
set Percent=%%
|
||||
|
||||
set last=HEAD
|
||||
for /f %%t in ('git tag --sort=-taggerdate --merged ^| findstr v') do (
|
||||
echo generating changelog for !last!..%%t
|
||||
|
@ -30,7 +32,7 @@ for /f %%t in ('git tag --sort=-taggerdate --merged ^| findstr v') do (
|
|||
rem echo !last! ---^> %%t >> %logfile%
|
||||
echo ----------------------------------------------- >> %logfile%
|
||||
echo. >> %logfile%
|
||||
git log %%t..!last! --no-merges "--pretty=format:%%h %%ai %%<(10,trunc)%%an %%s" >> %logfile%
|
||||
git log %%t..!last! --no-merges "--pretty=format:!Percent!h !Percent!ai !Percent!<(10,trunc)!Percent!an !Percent!s" >> %logfile%
|
||||
echo. >> %logfile%
|
||||
echo. >> %logfile%
|
||||
set last=%%t
|
||||
|
|
20
build_scripts/git_tag_cleaner.sh
Executable file
20
build_scripts/git_tag_cleaner.sh
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/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
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 659423769541169457c41f71c8a038e2d64ba079
|
||||
Subproject commit 2ddc86fb575a61170f4c06a00152e3e7dc74c8f4
|
|
@ -1 +1 @@
|
|||
Subproject commit a7a430008b76e53727598c4d13106e7ce95221d7
|
||||
Subproject commit 402f32eda026c3ec3e429b5fb842e87ebd985d73
|
|
@ -44,6 +44,7 @@ SOURCES = FeedReaderPlugin.cpp \
|
|||
gui/FeedReaderFeedNotify.cpp \
|
||||
gui/FeedReaderUserNotify.cpp \
|
||||
gui/FeedReaderFeedItem.cpp \
|
||||
gui/FeedTreeWidget.cpp \
|
||||
util/CURLWrapper.cpp \
|
||||
util/XMLWrapper.cpp \
|
||||
util/HTMLWrapper.cpp \
|
||||
|
@ -64,6 +65,7 @@ HEADERS = FeedReaderPlugin.h \
|
|||
gui/FeedReaderFeedNotify.h \
|
||||
gui/FeedReaderUserNotify.h \
|
||||
gui/FeedReaderFeedItem.h \
|
||||
gui/FeedTreeWidget.h \
|
||||
util/CURLWrapper.h \
|
||||
util/XMLWrapper.h \
|
||||
util/HTMLWrapper.h \
|
||||
|
@ -121,6 +123,11 @@ win32 {
|
|||
#Have to reorder libs, else got /libs/lib/libcrypto.a(bio_lib.o):bio_lib.c:(.text+0x0): multiple definition of `BIO_new'
|
||||
LIBS = -lcurl -lxml2 -lz -lxslt -lws2_32 -lwldap32 -lssl -lcrypto -lgdi32 $${LIBS}
|
||||
|
||||
isEmpty(QMAKE_SH) {
|
||||
# MinGW
|
||||
LIBS += -lcrypt32
|
||||
}
|
||||
|
||||
# Check for msys2
|
||||
!isEmpty(PREFIX_MSYS2) {
|
||||
message(Use msys2 xml2.)
|
||||
|
|
|
@ -92,7 +92,7 @@ void FeedReaderPlugin::setInterfaces(RsPlugInInterfaces &interfaces)
|
|||
{
|
||||
mInterfaces = interfaces;
|
||||
|
||||
mFeedReader = new p3FeedReader(mPlugInHandler, mInterfaces.mGxsForums);
|
||||
mFeedReader = new p3FeedReader(mPlugInHandler, mInterfaces.mGxsForums, mInterfaces.mPosted);
|
||||
rsFeedReader = mFeedReader;
|
||||
|
||||
mNotify = new FeedReaderNotify();
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
#include "gui/common/UIStateHelper.h"
|
||||
|
||||
#include <retroshare/rsgxsforums.h>
|
||||
#include <retroshare/rsposted.h>
|
||||
#include <iostream>
|
||||
|
||||
#define TOKEN_TYPE_FORUM_GROUPS 1
|
||||
#define TOKEN_TYPE_POSTED_GROUPS 2
|
||||
|
||||
AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent)
|
||||
: QDialog(parent, Qt::Window), mFeedReader(feedReader), mNotify(notify), ui(new Ui::AddFeedDialog)
|
||||
|
@ -47,9 +49,12 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
|
|||
|
||||
mStateHelper->addWidget(TOKEN_TYPE_FORUM_GROUPS, ui->forumComboBox, UISTATE_LOADING_DISABLED);
|
||||
mStateHelper->addWidget(TOKEN_TYPE_FORUM_GROUPS, ui->buttonBox->button(QDialogButtonBox::Ok), UISTATE_LOADING_DISABLED);
|
||||
mStateHelper->addWidget(TOKEN_TYPE_POSTED_GROUPS, ui->postedComboBox, UISTATE_LOADING_DISABLED);
|
||||
mStateHelper->addWidget(TOKEN_TYPE_POSTED_GROUPS, ui->buttonBox->button(QDialogButtonBox::Ok), UISTATE_LOADING_DISABLED);
|
||||
|
||||
/* Setup TokenQueue */
|
||||
mTokenQueue = new TokenQueue(rsGxsForums->getTokenService(), this);
|
||||
mForumTokenQueue = new TokenQueue(rsGxsForums->getTokenService(), this);
|
||||
mPostedTokenQueue = new TokenQueue(rsPosted->getTokenService(), this);
|
||||
|
||||
/* Connect signals */
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(createFeed()));
|
||||
|
@ -59,18 +64,23 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
|
|||
connect(ui->useStandardStorageTimeCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardStorageTimeToggled()));
|
||||
connect(ui->useStandardUpdateInterval, SIGNAL(toggled(bool)), this, SLOT(useStandardUpdateIntervalToggled()));
|
||||
connect(ui->useStandardProxyCheckBox, SIGNAL(toggled(bool)), this, SLOT(useStandardProxyToggled()));
|
||||
connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(typeForumToggled()));
|
||||
connect(ui->typeForumCheckBox, SIGNAL(toggled(bool)), this, SLOT(typeForumToggled()));
|
||||
connect(ui->typePostedCheckBox, SIGNAL(toggled(bool)), this, SLOT(typePostedToggled()));
|
||||
connect(ui->typeLocalCheckBox, SIGNAL(toggled(bool)), this, SLOT(typeLocalToggled()));
|
||||
connect(ui->postedFirstImageCheckBox, SIGNAL(toggled(bool)), this, SLOT(postedFirstImageToggled()));
|
||||
connect(ui->previewButton, SIGNAL(clicked()), this, SLOT(preview()));
|
||||
|
||||
/* currently only for local feeds */
|
||||
connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumToggled()));
|
||||
connect(ui->saveCompletePageCheckBox, SIGNAL(toggled(bool)), this, SLOT(denyForumAndPostedToggled()));
|
||||
|
||||
connect(ui->urlLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate()));
|
||||
connect(ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(validate()));
|
||||
connect(ui->useInfoFromFeedCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->typeLocalRadio, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->typeForumRadio, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->typeLocalCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->typeForumCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->forumComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(validate()));
|
||||
connect(ui->typePostedCheckBox, SIGNAL(toggled(bool)), this, SLOT(validate()));
|
||||
connect(ui->postedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(validate()));
|
||||
|
||||
connect(ui->clearCachePushButton, SIGNAL(clicked()), this, SLOT(clearMessageCache()));
|
||||
|
||||
|
@ -79,13 +89,24 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
|
|||
|
||||
ui->activatedCheckBox->setChecked(true);
|
||||
mStateHelper->setWidgetEnabled(ui->forumComboBox, false);
|
||||
mStateHelper->setWidgetEnabled(ui->postedComboBox, false);
|
||||
ui->useInfoFromFeedCheckBox->setChecked(true);
|
||||
ui->updateForumInfoCheckBox->setEnabled(false);
|
||||
ui->updateForumInfoCheckBox->setChecked(true);
|
||||
ui->updatePostedInfoCheckBox->setEnabled(false);
|
||||
ui->updatePostedInfoCheckBox->setChecked(true);
|
||||
ui->postedFirstImageCheckBox->setEnabled(false);
|
||||
ui->postedFirstImageCheckBox->setChecked(false);
|
||||
ui->postedOnlyImageCheckBox->setEnabled(false);
|
||||
ui->postedOnlyImageCheckBox->setChecked(false);
|
||||
ui->postedShinkImageCheckBox->setEnabled(false);
|
||||
ui->postedShinkImageCheckBox->setChecked(true);
|
||||
ui->useAuthenticationCheckBox->setChecked(false);
|
||||
ui->useStandardStorageTimeCheckBox->setChecked(true);
|
||||
ui->useStandardUpdateInterval->setChecked(true);
|
||||
ui->useStandardProxyCheckBox->setChecked(true);
|
||||
ui->embedImagesCheckBox->setChecked(true);
|
||||
ui->saveCompletePageCheckBox->setEnabled(false);
|
||||
|
||||
/* not yet supported */
|
||||
ui->authenticationGroupBox->setEnabled(false);
|
||||
|
@ -98,6 +119,9 @@ AddFeedDialog::AddFeedDialog(RsFeedReader *feedReader, FeedReaderNotify *notify,
|
|||
/* fill own forums */
|
||||
requestForumGroups();
|
||||
|
||||
/* fill own posted */
|
||||
requestPostedGroups();
|
||||
|
||||
validate();
|
||||
|
||||
ui->urlLineEdit->setFocus();
|
||||
|
@ -112,7 +136,8 @@ AddFeedDialog::~AddFeedDialog()
|
|||
processSettings(false);
|
||||
|
||||
delete(ui);
|
||||
delete(mTokenQueue);
|
||||
delete(mForumTokenQueue);
|
||||
delete(mPostedTokenQueue);
|
||||
}
|
||||
|
||||
void AddFeedDialog::processSettings(bool load)
|
||||
|
@ -161,18 +186,66 @@ void AddFeedDialog::useStandardProxyToggled()
|
|||
|
||||
void AddFeedDialog::typeForumToggled()
|
||||
{
|
||||
bool checked = ui->typeForumRadio->isChecked();
|
||||
bool checked = ui->typeForumCheckBox->isChecked();
|
||||
mStateHelper->setWidgetEnabled(ui->forumComboBox, checked);
|
||||
ui->updateForumInfoCheckBox->setEnabled(checked);
|
||||
|
||||
if (checked) {
|
||||
ui->typeLocalCheckBox->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::denyForumToggled()
|
||||
void AddFeedDialog::postedFirstImageToggled()
|
||||
{
|
||||
bool checked = ui->postedFirstImageCheckBox->isChecked();
|
||||
ui->postedOnlyImageCheckBox->setEnabled(checked);
|
||||
|
||||
if (!checked) {
|
||||
ui->postedOnlyImageCheckBox->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::typePostedToggled()
|
||||
{
|
||||
bool checked = ui->typePostedCheckBox->isChecked();
|
||||
mStateHelper->setWidgetEnabled(ui->postedComboBox, checked);
|
||||
ui->updatePostedInfoCheckBox->setEnabled(checked);
|
||||
ui->postedFirstImageCheckBox->setEnabled(checked);
|
||||
ui->postedShinkImageCheckBox->setEnabled(checked);
|
||||
|
||||
if (checked) {
|
||||
ui->typeLocalCheckBox->setChecked(false);
|
||||
}else {
|
||||
ui->postedFirstImageCheckBox->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::typeLocalToggled()
|
||||
{
|
||||
bool checked = ui->typeLocalCheckBox->isChecked();
|
||||
if (checked) {
|
||||
mStateHelper->setWidgetEnabled(ui->forumComboBox, false);
|
||||
mStateHelper->setWidgetEnabled(ui->postedComboBox, false);
|
||||
ui->typeForumCheckBox->setChecked(false);
|
||||
ui->typePostedCheckBox->setChecked(false);
|
||||
ui->saveCompletePageCheckBox->setEnabled(true);
|
||||
} else {
|
||||
ui->saveCompletePageCheckBox->setEnabled(false);
|
||||
ui->saveCompletePageCheckBox->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::denyForumAndPostedToggled()
|
||||
{
|
||||
if (ui->saveCompletePageCheckBox->isChecked()) {
|
||||
ui->typeForumRadio->setEnabled(false);
|
||||
ui->typeLocalRadio->setChecked(true);
|
||||
ui->typeForumCheckBox->setEnabled(false);
|
||||
ui->typeForumCheckBox->setChecked(false);
|
||||
ui->typePostedCheckBox->setEnabled(false);
|
||||
ui->typePostedCheckBox->setChecked(false);
|
||||
ui->typeLocalCheckBox->setChecked(true);
|
||||
} else {
|
||||
ui->typeForumRadio->setEnabled(true);
|
||||
ui->typeForumCheckBox->setEnabled(true);
|
||||
ui->typePostedCheckBox->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,11 +262,15 @@ void AddFeedDialog::validate()
|
|||
|
||||
ui->previewButton->setEnabled(ok);
|
||||
|
||||
if (!ui->typeLocalRadio->isChecked() && !ui->typeForumRadio->isChecked()) {
|
||||
if (!ui->typeLocalCheckBox->isChecked() && !ui->typeForumCheckBox->isChecked() && !ui->typePostedCheckBox->isChecked()) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ui->typeForumRadio->isChecked() && ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().isEmpty()) {
|
||||
if (ui->typeForumCheckBox->isChecked() && ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().isEmpty()) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ui->typePostedCheckBox->isChecked() && ui->postedComboBox->itemData(ui->postedComboBox->currentIndex()).toString().isEmpty()) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
@ -224,20 +301,32 @@ bool AddFeedDialog::fillFeed(uint32_t feedId)
|
|||
ui->urlLineEdit->setText(QString::fromUtf8(feedInfo.url.c_str()));
|
||||
ui->useInfoFromFeedCheckBox->setChecked(feedInfo.flag.infoFromFeed);
|
||||
ui->updateForumInfoCheckBox->setChecked(feedInfo.flag.updateForumInfo);
|
||||
ui->updatePostedInfoCheckBox->setChecked(feedInfo.flag.updatePostedInfo);
|
||||
ui->postedFirstImageCheckBox->setChecked(feedInfo.flag.postedFirstImage);
|
||||
ui->postedOnlyImageCheckBox->setChecked(feedInfo.flag.postedOnlyImage);
|
||||
ui->postedShinkImageCheckBox->setChecked(feedInfo.flag.postedShrinkImage);
|
||||
ui->activatedCheckBox->setChecked(!feedInfo.flag.deactivated);
|
||||
ui->embedImagesCheckBox->setChecked(feedInfo.flag.embedImages);
|
||||
ui->saveCompletePageCheckBox->setChecked(feedInfo.flag.saveCompletePage);
|
||||
|
||||
ui->descriptionPlainTextEdit->setPlainText(QString::fromUtf8(feedInfo.description.c_str()));
|
||||
|
||||
if (feedInfo.flag.forum || feedInfo.flag.posted) {
|
||||
if (feedInfo.flag.forum) {
|
||||
mStateHelper->setWidgetEnabled(ui->forumComboBox, true);
|
||||
ui->typeForumRadio->setChecked(true);
|
||||
ui->saveCompletePageCheckBox->setEnabled(false);
|
||||
ui->typeForumCheckBox->setChecked(true);
|
||||
|
||||
setActiveForumId(feedInfo.forumId);
|
||||
}
|
||||
if (feedInfo.flag.posted) {
|
||||
mStateHelper->setWidgetEnabled(ui->postedComboBox, true);
|
||||
ui->typePostedCheckBox->setChecked(true);
|
||||
|
||||
setActivePostedId(feedInfo.postedId);
|
||||
}
|
||||
ui->saveCompletePageCheckBox->setEnabled(false);
|
||||
} else {
|
||||
ui->typeLocalRadio->setChecked(true);
|
||||
ui->typeLocalCheckBox->setChecked(true);
|
||||
mStateHelper->setWidgetEnabled(ui->forumComboBox, false);
|
||||
}
|
||||
|
||||
|
@ -286,6 +375,21 @@ void AddFeedDialog::setActiveForumId(const std::string &forumId)
|
|||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::setActivePostedId(const std::string &postedId)
|
||||
{
|
||||
if (mStateHelper->isLoading(TOKEN_TYPE_POSTED_GROUPS)) {
|
||||
mFillPostedId = postedId;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = ui->postedComboBox->findData(QString::fromStdString(postedId));
|
||||
if (index >= 0) {
|
||||
ui->postedComboBox->setCurrentIndex(index);
|
||||
} else {
|
||||
ui->postedComboBox->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo)
|
||||
{
|
||||
feedInfo.parentId = mParentId;
|
||||
|
@ -294,18 +398,28 @@ void AddFeedDialog::getFeedInfo(FeedInfo &feedInfo)
|
|||
feedInfo.url = ui->urlLineEdit->text().toUtf8().constData();
|
||||
feedInfo.flag.infoFromFeed = ui->useInfoFromFeedCheckBox->isChecked();
|
||||
feedInfo.flag.updateForumInfo = ui->updateForumInfoCheckBox->isChecked() && ui->updateForumInfoCheckBox->isEnabled();
|
||||
feedInfo.flag.updatePostedInfo = ui->updatePostedInfoCheckBox->isChecked() && ui->updatePostedInfoCheckBox->isEnabled();
|
||||
feedInfo.flag.postedFirstImage = ui->postedFirstImageCheckBox->isChecked() && ui->postedFirstImageCheckBox->isEnabled();
|
||||
feedInfo.flag.postedOnlyImage = ui->postedOnlyImageCheckBox->isChecked() && ui->postedOnlyImageCheckBox->isEnabled();
|
||||
feedInfo.flag.postedShrinkImage = ui->postedShinkImageCheckBox->isChecked() && ui->postedShinkImageCheckBox->isEnabled();
|
||||
feedInfo.flag.deactivated = !ui->activatedCheckBox->isChecked();
|
||||
feedInfo.flag.embedImages = ui->embedImagesCheckBox->isChecked();
|
||||
feedInfo.flag.saveCompletePage = ui->saveCompletePageCheckBox->isChecked();
|
||||
|
||||
feedInfo.description = ui->descriptionPlainTextEdit->toPlainText().toUtf8().constData();
|
||||
|
||||
feedInfo.flag.forum = ui->typeForumRadio->isChecked();
|
||||
feedInfo.flag.forum = ui->typeForumCheckBox->isChecked();
|
||||
|
||||
if (feedInfo.flag.forum) {
|
||||
feedInfo.forumId = ui->forumComboBox->itemData(ui->forumComboBox->currentIndex()).toString().toStdString();
|
||||
}
|
||||
|
||||
feedInfo.flag.posted = ui->typePostedCheckBox->isChecked();
|
||||
|
||||
if (feedInfo.flag.posted) {
|
||||
feedInfo.postedId = ui->postedComboBox->itemData(ui->postedComboBox->currentIndex()).toString().toStdString();
|
||||
}
|
||||
|
||||
feedInfo.flag.authentication = ui->useAuthenticationCheckBox->isChecked();
|
||||
feedInfo.user = ui->userLineEdit->text().toUtf8().constData();
|
||||
feedInfo.password = ui->passwordLineEdit->text().toUtf8().constData();
|
||||
|
@ -340,12 +454,12 @@ void AddFeedDialog::createFeed()
|
|||
|
||||
if (mFeedId == 0) {
|
||||
/* add new feed */
|
||||
RsFeedAddResult result = mFeedReader->addFeed(feedInfo, mFeedId);
|
||||
RsFeedResult result = mFeedReader->addFeed(feedInfo, mFeedId);
|
||||
if (FeedReaderStringDefs::showError(this, result, tr("Create feed"), tr("Cannot create feed."))) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
RsFeedAddResult result = mFeedReader->setFeed(mFeedId, feedInfo);
|
||||
RsFeedResult result = mFeedReader->setFeed(mFeedId, feedInfo);
|
||||
if (FeedReaderStringDefs::showError(this, result, tr("Edit feed"), tr("Cannot change feed."))) {
|
||||
return;
|
||||
}
|
||||
|
@ -382,10 +496,10 @@ void AddFeedDialog::requestForumGroups()
|
|||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
|
||||
mTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_FORUM_GROUPS);
|
||||
mForumTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_FORUM_GROUPS);
|
||||
|
||||
uint32_t token;
|
||||
mTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_FORUM_GROUPS);
|
||||
mForumTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_FORUM_GROUPS);
|
||||
}
|
||||
|
||||
void AddFeedDialog::loadForumGroups(const uint32_t &token)
|
||||
|
@ -416,9 +530,50 @@ void AddFeedDialog::loadForumGroups(const uint32_t &token)
|
|||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::requestPostedGroups()
|
||||
{
|
||||
mStateHelper->setLoading(TOKEN_TYPE_POSTED_GROUPS, true);
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
|
||||
mPostedTokenQueue->cancelActiveRequestTokens(TOKEN_TYPE_POSTED_GROUPS);
|
||||
|
||||
uint32_t token;
|
||||
mPostedTokenQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, TOKEN_TYPE_POSTED_GROUPS);
|
||||
}
|
||||
|
||||
void AddFeedDialog::loadPostedGroups(const uint32_t &token)
|
||||
{
|
||||
std::vector<RsPostedGroup> groups;
|
||||
rsPosted->getGroupData(token, groups);
|
||||
|
||||
ui->postedComboBox->clear();
|
||||
|
||||
for (std::vector<RsPostedGroup>::iterator it = groups.begin(); it != groups.end(); ++it) {
|
||||
const RsPostedGroup &group = *it;
|
||||
|
||||
/* show only own posted */
|
||||
if (IS_GROUP_PUBLISHER(group.mMeta.mSubscribeFlags) && IS_GROUP_ADMIN(group.mMeta.mSubscribeFlags) && !group.mMeta.mAuthorId.isNull()) {
|
||||
ui->postedComboBox->addItem(QString::fromUtf8(group.mMeta.mGroupName.c_str()), QString::fromStdString(group.mMeta.mGroupId.toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
/* insert empty item */
|
||||
ui->postedComboBox->insertItem(0, "", "");
|
||||
ui->postedComboBox->setCurrentIndex(0);
|
||||
|
||||
mStateHelper->setLoading(TOKEN_TYPE_POSTED_GROUPS, false);
|
||||
|
||||
if (!mFillPostedId.empty()) {
|
||||
setActivePostedId(mFillPostedId);
|
||||
mFillPostedId.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void AddFeedDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
{
|
||||
if (queue == mTokenQueue)
|
||||
if (queue == mForumTokenQueue)
|
||||
{
|
||||
/* now switch on req */
|
||||
switch(req.mUserType)
|
||||
|
@ -433,4 +588,20 @@ void AddFeedDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
if (queue == mPostedTokenQueue)
|
||||
{
|
||||
/* now switch on req */
|
||||
switch(req.mUserType)
|
||||
{
|
||||
case TOKEN_TYPE_POSTED_GROUPS:
|
||||
loadPostedGroups(req.mToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "AddFeedDialog::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,10 @@ private slots:
|
|||
void useStandardUpdateIntervalToggled();
|
||||
void useStandardProxyToggled();
|
||||
void typeForumToggled();
|
||||
void denyForumToggled();
|
||||
void postedFirstImageToggled();
|
||||
void typePostedToggled();
|
||||
void typeLocalToggled();
|
||||
void denyForumAndPostedToggled();
|
||||
void validate();
|
||||
void createFeed();
|
||||
void preview();
|
||||
|
@ -63,9 +66,12 @@ private:
|
|||
void processSettings(bool load);
|
||||
void getFeedInfo(FeedInfo &feedInfo);
|
||||
void setActiveForumId(const std::string &forumId);
|
||||
void setActivePostedId(const std::string &postedId);
|
||||
|
||||
void requestForumGroups();
|
||||
void loadForumGroups(const uint32_t &token);
|
||||
void requestPostedGroups();
|
||||
void loadPostedGroups(const uint32_t &token);
|
||||
|
||||
private:
|
||||
RsFeedReader *mFeedReader;
|
||||
|
@ -73,13 +79,15 @@ private:
|
|||
uint32_t mFeedId;
|
||||
uint32_t mParentId;
|
||||
std::string mFillForumId;
|
||||
std::string mFillPostedId;
|
||||
|
||||
RsFeedTransformationType mTransformationType;
|
||||
std::list<std::string> mXPathsToUse;
|
||||
std::list<std::string> mXPathsToRemove;
|
||||
std::string mXslt;
|
||||
|
||||
TokenQueue *mTokenQueue;
|
||||
TokenQueue *mForumTokenQueue;
|
||||
TokenQueue *mPostedTokenQueue;
|
||||
UIStateHelper *mStateHelper;
|
||||
|
||||
Ui::AddFeedDialog *ui;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1068</width>
|
||||
<height>880</height>
|
||||
<width>739</width>
|
||||
<height>653</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -45,48 +45,6 @@
|
|||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gradFrame_GL">
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="typeGroupBox">
|
||||
<property name="title">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="typeForumRadio">
|
||||
<property name="text">
|
||||
<string>Forum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="RSComboBox" name="forumComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="typeLocalRadio">
|
||||
<property name="text">
|
||||
<string>Local Feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QGroupBox" name="authenticationGroupBox">
|
||||
<property name="title">
|
||||
|
@ -309,7 +267,6 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
|
@ -324,7 +281,44 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="3" column="1">
|
||||
<widget class="QGroupBox" name="flagGroupBox">
|
||||
<property name="title">
|
||||
<string>Misc</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="activatedCheckBox">
|
||||
<property name="text">
|
||||
<string>Activated</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useInfoFromFeedCheckBox">
|
||||
<property name="text">
|
||||
<string>Use name and description from feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="embedImagesCheckBox">
|
||||
<property name="text">
|
||||
<string>Embed images</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="saveCompletePageCheckBox">
|
||||
<property name="text">
|
||||
<string>Save complete web page (experimental for local feeds)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Transformation</string>
|
||||
|
@ -357,26 +351,49 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" rowspan="2">
|
||||
<widget class="QGroupBox" name="flagGroupBox">
|
||||
<item row="3" column="0" rowspan="3">
|
||||
<widget class="QGroupBox" name="typeGroupBox">
|
||||
<property name="title">
|
||||
<string>Misc</string>
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="typeForumCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="activatedCheckBox">
|
||||
<property name="text">
|
||||
<string>Activated</string>
|
||||
<string>Forum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="useInfoFromFeedCheckBox">
|
||||
<item row="0" column="1">
|
||||
<widget class="RSComboBox" name="forumComboBox"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QCheckBox" name="typeLocalCheckBox">
|
||||
<property name="text">
|
||||
<string>Use name and description from feed</string>
|
||||
<string>Local Feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="updateForumInfoCheckBox">
|
||||
<property name="text">
|
||||
|
@ -384,20 +401,50 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="embedImagesCheckBox">
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="RSComboBox" name="postedComboBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="typePostedCheckBox">
|
||||
<property name="text">
|
||||
<string>Embed images</string>
|
||||
<string>Board</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="saveCompletePageCheckBox">
|
||||
<item row="6" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="updatePostedInfoCheckBox">
|
||||
<property name="text">
|
||||
<string>Save complete web page (experimental for local feeds)</string>
|
||||
<string>Update board information</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="postedOnlyImageCheckBox">
|
||||
<property name="text">
|
||||
<string>Only image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="postedFirstImageCheckBox">
|
||||
<property name="text">
|
||||
<string>Use first image as board image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="postedShinkImageCheckBox">
|
||||
<property name="text">
|
||||
<string>Shrink image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -423,22 +470,32 @@
|
|||
<tabstop>urlLineEdit</tabstop>
|
||||
<tabstop>nameLineEdit</tabstop>
|
||||
<tabstop>descriptionPlainTextEdit</tabstop>
|
||||
<tabstop>typeForumRadio</tabstop>
|
||||
<tabstop>typeForumCheckBox</tabstop>
|
||||
<tabstop>forumComboBox</tabstop>
|
||||
<tabstop>updateForumInfoCheckBox</tabstop>
|
||||
<tabstop>typePostedCheckBox</tabstop>
|
||||
<tabstop>postedComboBox</tabstop>
|
||||
<tabstop>updatePostedInfoCheckBox</tabstop>
|
||||
<tabstop>postedShinkImageCheckBox</tabstop>
|
||||
<tabstop>postedFirstImageCheckBox</tabstop>
|
||||
<tabstop>postedOnlyImageCheckBox</tabstop>
|
||||
<tabstop>typeLocalCheckBox</tabstop>
|
||||
<tabstop>activatedCheckBox</tabstop>
|
||||
<tabstop>useInfoFromFeedCheckBox</tabstop>
|
||||
<tabstop>updateForumInfoCheckBox</tabstop>
|
||||
<tabstop>embedImagesCheckBox</tabstop>
|
||||
<tabstop>saveCompletePageCheckBox</tabstop>
|
||||
<tabstop>previewButton</tabstop>
|
||||
<tabstop>useAuthenticationCheckBox</tabstop>
|
||||
<tabstop>userLineEdit</tabstop>
|
||||
<tabstop>passwordLineEdit</tabstop>
|
||||
<tabstop>useStandardStorageTimeCheckBox</tabstop>
|
||||
<tabstop>clearCachePushButton</tabstop>
|
||||
<tabstop>storageTimeSpinBox</tabstop>
|
||||
<tabstop>useStandardUpdateInterval</tabstop>
|
||||
<tabstop>updateIntervalSpinBox</tabstop>
|
||||
<tabstop>useStandardProxyCheckBox</tabstop>
|
||||
<tabstop>proxyAddressLineEdit</tabstop>
|
||||
<tabstop>proxyPortSpinBox</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QInputDialog>
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
#include <QBuffer>
|
||||
|
||||
#include "FeedReaderDialog.h"
|
||||
#include "FeedReaderMessageWidget.h"
|
||||
|
@ -35,6 +36,8 @@
|
|||
#include "gui/settings/rsharesettings.h"
|
||||
#include "gui/notifyqt.h"
|
||||
#include "FeedReaderUserNotify.h"
|
||||
#include "gui/Posted/PostedCreatePostDialog.h"
|
||||
#include "util/imageutil.h"
|
||||
|
||||
#include "interface/rsFeedReader.h"
|
||||
#include "retroshare/rsiface.h"
|
||||
|
@ -55,6 +58,8 @@
|
|||
#define ROLE_FEED_ERROR Qt::UserRole + 9
|
||||
#define ROLE_FEED_DEACTIVATED Qt::UserRole + 10
|
||||
|
||||
const int MAXMESSAGESIZE = RsSerialiser::MAX_SERIAL_SIZE - 70000;
|
||||
|
||||
FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent)
|
||||
: MainPage(parent), mFeedReader(feedReader), mNotify(notify), ui(new Ui::FeedReaderDialog)
|
||||
{
|
||||
|
@ -66,6 +71,7 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n
|
|||
mMessageWidget = NULL;
|
||||
|
||||
connect(mNotify, &FeedReaderNotify::feedChanged, this, &FeedReaderDialog::feedChanged, Qt::QueuedConnection);
|
||||
connect(mNotify, &FeedReaderNotify::optimizeImage, this, &FeedReaderDialog::optimizeImage, Qt::QueuedConnection);
|
||||
|
||||
connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
|
||||
|
||||
|
@ -84,9 +90,16 @@ FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *n
|
|||
connect(ui->feedAddButton, SIGNAL(clicked()), this, SLOT(newFeed()));
|
||||
connect(ui->feedProcessButton, SIGNAL(clicked()), this, SLOT(processFeed()));
|
||||
|
||||
connect(ui->feedTreeWidget, SIGNAL(feedReparent(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedTreeReparent(QTreeWidgetItem*,QTreeWidgetItem*)));
|
||||
|
||||
mFeedCompareRole = new RSTreeWidgetItemCompareRole;
|
||||
mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT);
|
||||
|
||||
/* enable drag and drop */
|
||||
ui->feedTreeWidget->setAcceptDrops(true);
|
||||
ui->feedTreeWidget->setDragEnabled(true);
|
||||
ui->feedTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
|
||||
/* initialize root item */
|
||||
mRootItem = new QTreeWidgetItem(ui->feedTreeWidget);
|
||||
QString name = tr("Message Folders");
|
||||
|
@ -395,6 +408,9 @@ void FeedReaderDialog::updateFeeds(uint32_t parentId, QTreeWidgetItem *parentIte
|
|||
mOpenFeedIds->removeAt(index);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* disable drop */
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,6 +610,55 @@ void FeedReaderDialog::feedChanged(uint32_t feedId, int type)
|
|||
calculateFeedItems();
|
||||
}
|
||||
|
||||
void FeedReaderDialog::optimizeImage()
|
||||
{
|
||||
while (true) {
|
||||
FeedReaderOptimizeImageTask *optimizeImageTask = mFeedReader->getOptimizeImageTask();
|
||||
|
||||
if (!optimizeImageTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
optimizeImageTask->mResult = false;
|
||||
|
||||
QImage image;
|
||||
if (image.loadFromData(optimizeImageTask->mImage.data(), optimizeImageTask->mImage.size())) {
|
||||
QByteArray optimizedImageData;
|
||||
std::string optimizedImageMimeType;
|
||||
QImage imageOptDummy;
|
||||
|
||||
switch (optimizeImageTask->mType) {
|
||||
case FeedReaderOptimizeImageTask::POSTED:
|
||||
if (PostedCreatePostDialog::optimizeImage(image, optimizedImageData, imageOptDummy)) {
|
||||
optimizedImageMimeType = "image/jpeg";
|
||||
optimizeImageTask->mResult = true;
|
||||
}
|
||||
break;
|
||||
case FeedReaderOptimizeImageTask::SIZE:
|
||||
if (ImageUtil::optimizeSizeBytes(optimizedImageData, image, imageOptDummy, "JPG", 0, MAXMESSAGESIZE)) {
|
||||
optimizedImageMimeType = "image/jpg";
|
||||
optimizeImageTask->mResult = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (optimizeImageTask->mResult) {
|
||||
if (optimizedImageData.size() < (ssize_t) optimizeImageTask->mImage.size()) {
|
||||
/* use optimized image */
|
||||
optimizeImageTask->mImageResult.assign(optimizedImageData.begin(), optimizedImageData.end());
|
||||
optimizeImageTask->mMimeTypeResult = optimizedImageMimeType;
|
||||
} else {
|
||||
/* use original image */
|
||||
optimizeImageTask->mImageResult = optimizeImageTask->mImage;
|
||||
optimizeImageTask->mMimeTypeResult = optimizeImageTask->mMimeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mFeedReader->setOptimizeImageTaskResult(optimizeImageTask);
|
||||
}
|
||||
}
|
||||
|
||||
FeedReaderMessageWidget *FeedReaderDialog::feedMessageWidget(uint32_t id)
|
||||
{
|
||||
int tabCount = ui->messageTabWidget->count();
|
||||
|
@ -738,7 +803,7 @@ void FeedReaderDialog::newFolder()
|
|||
|
||||
if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) {
|
||||
uint32_t feedId;
|
||||
RsFeedAddResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId);
|
||||
RsFeedResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId);
|
||||
FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder."));
|
||||
}
|
||||
}
|
||||
|
@ -791,7 +856,7 @@ void FeedReaderDialog::editFeed()
|
|||
dialog.setTextValue(item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString());
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) {
|
||||
RsFeedAddResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData());
|
||||
RsFeedResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData());
|
||||
FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder."));
|
||||
}
|
||||
} else {
|
||||
|
@ -832,3 +897,30 @@ void FeedReaderDialog::processFeed()
|
|||
|
||||
mFeedReader->processFeed(feedId);
|
||||
}
|
||||
|
||||
void FeedReaderDialog::feedTreeReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent)
|
||||
{
|
||||
if (!item || ! newParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
|
||||
uint32_t parentId = newParent->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
|
||||
|
||||
if (feedId == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RsFeedResult result = mFeedReader->setParent(feedId, parentId);
|
||||
if (FeedReaderStringDefs::showError(this, result, tr("Move feed"), tr("Cannot move feed."))) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool expanded = item->isExpanded();
|
||||
item->parent()->removeChild(item);
|
||||
newParent->addChild(item);
|
||||
item->setExpanded(expanded);
|
||||
newParent->setExpanded(true);
|
||||
|
||||
calculateFeedItems();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ private slots:
|
|||
void editFeed();
|
||||
void activateFeed();
|
||||
void processFeed();
|
||||
void feedTreeReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent);
|
||||
|
||||
void messageTabCloseRequested(int index);
|
||||
void messageTabChanged(int index);
|
||||
|
@ -68,6 +69,7 @@ private slots:
|
|||
|
||||
/* FeedReaderNotify */
|
||||
void feedChanged(uint32_t feedId, int type);
|
||||
void optimizeImage();
|
||||
|
||||
private:
|
||||
uint32_t currentFeedId();
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="RSTreeWidget" name="feedTreeWidget">
|
||||
<widget class="FeedTreeWidget" name="feedTreeWidget">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
|
@ -186,9 +186,9 @@
|
|||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RSTreeWidget</class>
|
||||
<class>FeedTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>gui/common/RSTreeWidget.h</header>
|
||||
<header>gui/FeedTreeWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RSTabWidget</class>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QDesktopServices>
|
||||
#include <QTimer>
|
||||
#include <QPainter>
|
||||
#include <QMimeData>
|
||||
|
||||
#include "FeedReaderMessageWidget.h"
|
||||
#include "ui_FeedReaderMessageWidget.h"
|
||||
|
@ -36,8 +37,14 @@
|
|||
#include "gui/settings/rsharesettings.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "gui/Posted/PostedCreatePostDialog.h"
|
||||
#include "gui/gxsforums/CreateGxsForumMsg.h"
|
||||
#include "gui/common/FilesDefs.h"
|
||||
#include "util/imageutil.h"
|
||||
|
||||
#include "retroshare/rsiface.h"
|
||||
#include "retroshare/rsgxsforums.h"
|
||||
#include "retroshare/rsposted.h"
|
||||
|
||||
#define COLUMN_MSG_COUNT 4
|
||||
#define COLUMN_MSG_TITLE 0
|
||||
|
@ -83,6 +90,12 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader *
|
|||
connect(ui->msgRemoveButton, SIGNAL(clicked()), this, SLOT(removeMsg()));
|
||||
connect(ui->feedProcessButton, SIGNAL(clicked()), this, SLOT(processFeed()));
|
||||
|
||||
/* Set initial size the splitter */
|
||||
QList<int> sizes;
|
||||
sizes << 250 << width(); // Qt calculates the right sizes
|
||||
ui->pictureSplitter->setSizes(sizes);
|
||||
ui->pictureSplitter->hide();
|
||||
|
||||
// create timer for navigation
|
||||
mTimer = new QTimer(this);
|
||||
mTimer->setInterval(300);
|
||||
|
@ -115,6 +128,10 @@ FeedReaderMessageWidget::FeedReaderMessageWidget(uint32_t feedId, RsFeedReader *
|
|||
ui->filterLineEdit->addFilter(QIcon(), tr("Author"), COLUMN_MSG_AUTHOR, tr("Search Author"));
|
||||
ui->filterLineEdit->setCurrentFilter(COLUMN_MSG_TITLE);
|
||||
|
||||
/* add image actions */
|
||||
ui->attachmentLabel->addContextMenuAction(ui->actionAttachmentCopyLinkLocation);
|
||||
connect(ui->actionAttachmentCopyLinkLocation, &QAction::triggered, this, &FeedReaderMessageWidget::attachmentCopyLinkLocation);
|
||||
|
||||
/* load settings */
|
||||
processSettings(true);
|
||||
|
||||
|
@ -175,6 +192,7 @@ void FeedReaderMessageWidget::processSettings(bool load)
|
|||
|
||||
// state of splitter
|
||||
ui->msgSplitter->restoreState(Settings->value("msgSplitter").toByteArray());
|
||||
ui->pictureSplitter->restoreState(Settings->value("pictureSplitter").toByteArray());
|
||||
} else {
|
||||
// save settings
|
||||
|
||||
|
@ -183,6 +201,7 @@ void FeedReaderMessageWidget::processSettings(bool load)
|
|||
|
||||
// state of splitter
|
||||
Settings->setValue("msgSplitter", ui->msgSplitter->saveState());
|
||||
Settings->setValue("pictureSplitter", ui->pictureSplitter->saveState());
|
||||
}
|
||||
|
||||
Settings->endGroup();
|
||||
|
@ -245,9 +264,19 @@ void FeedReaderMessageWidget::setFeedId(uint32_t feedId)
|
|||
ui->msgReadAllButton->setEnabled(false);
|
||||
ui->msgTreeWidget->setPlaceholderText("");
|
||||
} else {
|
||||
if (mFeedInfo.flag.forum) {
|
||||
if (mFeedInfo.flag.forum || mFeedInfo.flag.posted) {
|
||||
ui->msgReadAllButton->setEnabled(false);
|
||||
|
||||
if (mFeedInfo.flag.forum && mFeedInfo.flag.posted) {
|
||||
ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum and the board"));
|
||||
} else {
|
||||
if (mFeedInfo.flag.forum) {
|
||||
ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the forum"));
|
||||
}
|
||||
if (mFeedInfo.flag.posted) {
|
||||
ui->msgTreeWidget->setPlaceholderText(tr("The messages will be added to the board"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui->msgReadAllButton->setEnabled(true);
|
||||
ui->msgTreeWidget->setPlaceholderText("");
|
||||
|
@ -340,6 +369,20 @@ void FeedReaderMessageWidget::msgTreeCustomPopupMenu(QPoint /*point*/)
|
|||
action = contextMnu.addAction(QIcon(""), tr("Remove"), this, SLOT(removeMsg()));
|
||||
action->setEnabled(!selectedItems.empty());
|
||||
|
||||
if (selectedItems.size() == 1 && (mFeedReader->forums() || mFeedReader->posted())) {
|
||||
contextMnu.addSeparator();
|
||||
|
||||
if (mFeedReader->forums()) {
|
||||
QMenu *menu = contextMnu.addMenu(tr("Add to forum"));
|
||||
connect(menu, SIGNAL(aboutToShow()), this, SLOT(fillForumMenu()));
|
||||
}
|
||||
|
||||
if (mFeedReader->posted()) {
|
||||
QMenu *menu = contextMnu.addMenu(tr("Add to board"));
|
||||
connect(menu, SIGNAL(aboutToShow()), this, SLOT(fillPostedMenu()));
|
||||
}
|
||||
}
|
||||
|
||||
contextMnu.addSeparator();
|
||||
|
||||
action = contextMnu.addAction(QIcon(""), tr("Retransform"), this, SLOT(retransformMsg()));
|
||||
|
@ -571,6 +614,21 @@ void FeedReaderMessageWidget::msgItemChanged()
|
|||
mTimer->start();
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::clearMessage()
|
||||
{
|
||||
ui->msgTitle->clear();
|
||||
// ui->msgLink->clear();
|
||||
ui->msgText->clear();
|
||||
ui->msgTextSplitter->clear();
|
||||
ui->attachmentLabel->clear();
|
||||
ui->linkButton->setEnabled(false);
|
||||
ui->msgText->show();
|
||||
ui->pictureSplitter->hide();
|
||||
|
||||
ui->actionAttachmentCopyLinkLocation->setData(QVariant());
|
||||
ui->actionAttachmentCopyLinkLocation->setEnabled(false);
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::updateCurrentMessage()
|
||||
{
|
||||
mTimer->stop();
|
||||
|
@ -580,10 +638,7 @@ void FeedReaderMessageWidget::updateCurrentMessage()
|
|||
std::string msgId = currentMsgId();
|
||||
|
||||
if (mFeedId == 0 || msgId.empty()) {
|
||||
ui->msgTitle->clear();
|
||||
// ui->msgLink->clear();
|
||||
ui->msgText->clear();
|
||||
ui->linkButton->setEnabled(false);
|
||||
clearMessage();
|
||||
|
||||
ui->msgReadButton->setEnabled(false);
|
||||
ui->msgUnreadButton->setEnabled(false);
|
||||
|
@ -594,10 +649,7 @@ void FeedReaderMessageWidget::updateCurrentMessage()
|
|||
QTreeWidgetItem *item = ui->msgTreeWidget->currentItem();
|
||||
if (!item) {
|
||||
/* there is something wrong */
|
||||
ui->msgTitle->clear();
|
||||
// ui->msgLink->clear();
|
||||
ui->msgText->clear();
|
||||
ui->linkButton->setEnabled(false);
|
||||
clearMessage();
|
||||
|
||||
ui->msgReadButton->setEnabled(false);
|
||||
ui->msgUnreadButton->setEnabled(false);
|
||||
|
@ -612,10 +664,7 @@ void FeedReaderMessageWidget::updateCurrentMessage()
|
|||
/* get msg */
|
||||
FeedMsgInfo msgInfo;
|
||||
if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) {
|
||||
ui->msgTitle->clear();
|
||||
// ui->msgLink->clear();
|
||||
ui->msgText->clear();
|
||||
ui->linkButton->setEnabled(false);
|
||||
clearMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -635,9 +684,41 @@ void FeedReaderMessageWidget::updateCurrentMessage()
|
|||
setMsgAsReadUnread(row, setToReadOnActive);
|
||||
}
|
||||
|
||||
ui->actionAttachmentCopyLinkLocation->setData(QVariant());
|
||||
ui->actionAttachmentCopyLinkLocation->setEnabled(false);
|
||||
|
||||
if (!msgInfo.attachment.empty()) {
|
||||
QByteArray imageData((char*) msgInfo.attachment.data(), msgInfo.attachment.size());
|
||||
QPixmap pixmap;
|
||||
if (pixmap.loadFromData(imageData)) {
|
||||
ui->attachmentLabel->setPixmap(pixmap);
|
||||
ui->pictureSplitter->show();
|
||||
ui->msgText->hide();
|
||||
} else {
|
||||
ui->pictureSplitter->hide();
|
||||
ui->msgText->show();
|
||||
}
|
||||
|
||||
if (!msgInfo.attachmentLink.empty()) {
|
||||
ui->actionAttachmentCopyLinkLocation->setData(QString::fromUtf8(msgInfo.attachmentLink.c_str()));
|
||||
ui->actionAttachmentCopyLinkLocation->setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
ui->pictureSplitter->hide();
|
||||
ui->msgText->show();
|
||||
}
|
||||
|
||||
QString msgTxt = RsHtml().formatText(ui->msgText->document(), QString::fromUtf8((msgInfo.descriptionTransformed.empty() ? msgInfo.description : msgInfo.descriptionTransformed).c_str()), RSHTML_FORMATTEXT_EMBED_LINKS);
|
||||
|
||||
if (ui->pictureSplitter->isVisible()) {
|
||||
ui->msgTextSplitter->setHtml(msgTxt);
|
||||
ui->msgText->clear();
|
||||
} else {
|
||||
ui->msgText->setHtml(msgTxt);
|
||||
ui->msgTextSplitter->clear();
|
||||
ui->attachmentLabel->clear();
|
||||
}
|
||||
|
||||
ui->msgTitle->setText(QString::fromUtf8(msgInfo.title.c_str()));
|
||||
|
||||
ui->linkButton->setEnabled(!msgInfo.link.empty());
|
||||
|
@ -714,11 +795,11 @@ void FeedReaderMessageWidget::toggleMsgText()
|
|||
void FeedReaderMessageWidget::toggleMsgText_internal()
|
||||
{
|
||||
if (ui->expandButton->isChecked()) {
|
||||
ui->msgText->setVisible(true);
|
||||
ui->horizontalLayoutWidget->setVisible(true);
|
||||
ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png")));
|
||||
ui->expandButton->setToolTip(tr("Hide"));
|
||||
} else {
|
||||
ui->msgText->setVisible(false);
|
||||
ui->horizontalLayoutWidget->setVisible(false);
|
||||
ui->expandButton->setIcon(QIcon(QString(":/images/edit_add24.png")));
|
||||
ui->expandButton->setToolTip(tr("Expand"));
|
||||
}
|
||||
|
@ -840,3 +921,123 @@ void FeedReaderMessageWidget::openLinkMsg()
|
|||
|
||||
QDesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::fillForumMenu()
|
||||
{
|
||||
QMenu *menu = dynamic_cast<QMenu*>(sender()) ;
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
|
||||
disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(fillForumMenu()));
|
||||
|
||||
std::vector<RsGxsForumGroup> groups;
|
||||
if (mFeedReader->getForumGroups(groups, true)) {
|
||||
for (std::vector<RsGxsForumGroup>::iterator it = groups.begin(); it != groups.end(); ++it) {
|
||||
const RsGxsForumGroup &group = *it;
|
||||
QAction *action = menu->addAction(QString::fromUtf8(group.mMeta.mGroupName.c_str()), this, SLOT(addToForum()));
|
||||
action->setData(QString::fromUtf8(group.mMeta.mGroupId.toStdString().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::fillPostedMenu()
|
||||
{
|
||||
QMenu *menu = dynamic_cast<QMenu*>(sender()) ;
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
|
||||
disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(fillPostedMenu()));
|
||||
|
||||
std::vector<RsPostedGroup> groups;
|
||||
if (mFeedReader->getPostedGroups(groups, true)) {
|
||||
for (std::vector<RsPostedGroup>::iterator it = groups.begin(); it != groups.end(); ++it) {
|
||||
const RsPostedGroup &group = *it;
|
||||
QAction *action = menu->addAction(QString::fromUtf8(group.mMeta.mGroupName.c_str()), this, SLOT(addToPosted()));
|
||||
action->setData(QString::fromUtf8(group.mMeta.mGroupId.toStdString().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::addToForum()
|
||||
{
|
||||
QAction *action = dynamic_cast<QAction*>(sender()) ;
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString id = action->data().toString();
|
||||
if (id.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||
if (selectedItems.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msgId = selectedItems[0]->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
||||
FeedMsgInfo msgInfo;
|
||||
if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RsGxsGroupId forumId(id.toStdString());
|
||||
|
||||
CreateGxsForumMsg *msgDialog = new CreateGxsForumMsg(forumId, RsGxsMessageId(), RsGxsMessageId(), RsGxsId()) ;
|
||||
msgDialog->setSubject(QString::fromUtf8(msgInfo.title.c_str()));
|
||||
msgDialog->insertPastedText(QString::fromUtf8(msgInfo.description.c_str()));
|
||||
msgDialog->show();
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::addToPosted()
|
||||
{
|
||||
QAction *action = dynamic_cast<QAction*>(sender()) ;
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString id = action->data().toString();
|
||||
if (id.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QTreeWidgetItem*> selectedItems = ui->msgTreeWidget->selectedItems();
|
||||
if (selectedItems.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string msgId = selectedItems[0]->data(COLUMN_MSG_DATA, ROLE_MSG_ID).toString().toStdString();
|
||||
FeedMsgInfo msgInfo;
|
||||
if (!mFeedReader->getMsgInfo(mFeedId, msgId, msgInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RsGxsGroupId postedId(id.toStdString());
|
||||
|
||||
PostedCreatePostDialog *msgDialog = new PostedCreatePostDialog(mFeedReader->posted(), postedId);
|
||||
msgDialog->setTitle(QString::fromUtf8(msgInfo.title.c_str()));
|
||||
msgDialog->setNotes(QString::fromUtf8(msgInfo.description.c_str()));
|
||||
msgDialog->setLink(QString::fromUtf8(msgInfo.link.c_str()));
|
||||
msgDialog->show();
|
||||
}
|
||||
|
||||
void FeedReaderMessageWidget::attachmentCopyLinkLocation()
|
||||
{
|
||||
QAction *action = dynamic_cast<QAction*>(sender()) ;
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant data = action->data();
|
||||
if (!data.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type() != QVariant::String) {
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::clipboard()->setText(data.toString());
|
||||
}
|
||||
|
|
|
@ -73,6 +73,11 @@ private slots:
|
|||
void openLinkMsg();
|
||||
void copyLinkMsg();
|
||||
void retransformMsg();
|
||||
void fillForumMenu();
|
||||
void fillPostedMenu();
|
||||
void addToForum();
|
||||
void addToPosted();
|
||||
void attachmentCopyLinkLocation();
|
||||
|
||||
/* FeedReaderNotify */
|
||||
void feedChanged(uint32_t feedId, int type);
|
||||
|
@ -88,6 +93,7 @@ private:
|
|||
void filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn);
|
||||
void filterItem(QTreeWidgetItem *item);
|
||||
void toggleMsgText_internal();
|
||||
void clearMessage();
|
||||
|
||||
bool mProcessSettings;
|
||||
RSTreeWidgetItemCompareRole *mMsgCompareRole;
|
||||
|
|
|
@ -182,7 +182,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/images/message-state-header.png</normaloff>:/images/message-state-header.png</iconset>
|
||||
</property>
|
||||
</column>
|
||||
|
@ -245,7 +245,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../retroshare-gui/src/gui/images.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/images/edit_remove24.png</normaloff>:/images/edit_remove24.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -260,6 +260,9 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<layout class="QHBoxLayout" name="pictureHorizontalLayout">
|
||||
<item>
|
||||
<widget class="RSTextBrowser" name="msgText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
|
@ -271,10 +274,50 @@
|
|||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="pictureSplitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="AspectRatioPixmapLabel" name="attachmentLabel">
|
||||
<property name="text">
|
||||
<string notr="true">pictureLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="RSTextBrowser" name="msgTextSplitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>10</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionAttachmentCopyLinkLocation">
|
||||
<property name="text">
|
||||
<string>Copy Link Location</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RSTextBrowser</class>
|
||||
|
@ -297,10 +340,14 @@
|
|||
<header location="global">gui/common/ElidedLabel.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AspectRatioPixmapLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">util/AspectRatioPixmapLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="FeedReader_images.qrc"/>
|
||||
<include location="../../../retroshare-gui/src/gui/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -33,3 +33,8 @@ void FeedReaderNotify::notifyMsgChanged(uint32_t feedId, const std::string &msgI
|
|||
{
|
||||
emit msgChanged(feedId, QString::fromStdString(msgId), type);
|
||||
}
|
||||
|
||||
void FeedReaderNotify::notifyOptimizeImage()
|
||||
{
|
||||
emit optimizeImage();
|
||||
}
|
||||
|
|
|
@ -34,10 +34,12 @@ public:
|
|||
/* RsFeedReaderNotify */
|
||||
virtual void notifyFeedChanged(uint32_t feedId, int type);
|
||||
virtual void notifyMsgChanged(uint32_t feedId, const std::string &msgId, int type);
|
||||
virtual void notifyOptimizeImage();
|
||||
|
||||
signals:
|
||||
void feedChanged(uint32_t feedId, int type);
|
||||
void msgChanged(uint32_t feedId, const QString &msgId, int type);
|
||||
void optimizeImage();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,27 +23,27 @@
|
|||
|
||||
#include "FeedReaderStringDefs.h"
|
||||
|
||||
bool FeedReaderStringDefs::showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text)
|
||||
bool FeedReaderStringDefs::showError(QWidget *parent, RsFeedResult result, const QString &title, const QString &text)
|
||||
{
|
||||
QString error;
|
||||
|
||||
switch (result) {
|
||||
case RS_FEED_ADD_RESULT_SUCCESS:
|
||||
case RS_FEED_RESULT_SUCCESS:
|
||||
/* no error */
|
||||
return false;
|
||||
case RS_FEED_ADD_RESULT_FEED_NOT_FOUND:
|
||||
case RS_FEED_RESULT_FEED_NOT_FOUND:
|
||||
error = QApplication::translate("FeedReaderStringDefs", "Feed not found.");
|
||||
break;
|
||||
case RS_FEED_ADD_RESULT_PARENT_NOT_FOUND:
|
||||
case RS_FEED_RESULT_PARENT_NOT_FOUND:
|
||||
error = QApplication::translate("FeedReaderStringDefs", "Parent not found.");
|
||||
break;
|
||||
case RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER:
|
||||
case RS_FEED_RESULT_PARENT_IS_NO_FOLDER:
|
||||
error = QApplication::translate("FeedReaderStringDefs", "Parent is no folder.");
|
||||
break;
|
||||
case RS_FEED_ADD_RESULT_FEED_IS_FOLDER:
|
||||
case RS_FEED_RESULT_FEED_IS_FOLDER:
|
||||
error = QApplication::translate("FeedReaderStringDefs", "Feed is a folder.");
|
||||
break;
|
||||
case RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER:
|
||||
case RS_FEED_RESULT_FEED_IS_NO_FOLDER:
|
||||
error = QApplication::translate("FeedReaderStringDefs", "Feed is no folder.");
|
||||
break;
|
||||
default:
|
||||
|
@ -101,6 +101,9 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
|
|||
case RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Unknown response code");
|
||||
break;
|
||||
case RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Download blocked");
|
||||
break;
|
||||
|
||||
/* process */
|
||||
case RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR:
|
||||
|
@ -109,9 +112,9 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
|
|||
case RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Unknown XML format");
|
||||
break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Can't create forum");
|
||||
break;
|
||||
// case RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE:
|
||||
// errorText = QApplication::translate("FeedReaderStringDefs", "Can't create forum");
|
||||
// break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Forum not found");
|
||||
break;
|
||||
|
@ -121,6 +124,21 @@ QString FeedReaderStringDefs::errorString(RsFeedReaderErrorState errorState, con
|
|||
case RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_AUTHOR:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Forum has no author");
|
||||
break;
|
||||
// case RS_FEED_ERRORSTATE_PROCESS_POSTED_CREATE:
|
||||
// errorText = QApplication::translate("FeedReaderStringDefs", "Can't create board");
|
||||
// break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Board not found");
|
||||
break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_ADMIN:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "You are not admin of the board");
|
||||
break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_AUTHOR:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Board has no author");
|
||||
break;
|
||||
case RS_FEED_ERRORSTATE_PROCESS_POST:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Some posts could not be created");
|
||||
break;
|
||||
|
||||
case RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR:
|
||||
errorText = QApplication::translate("FeedReaderStringDefs", "Can't read html");
|
||||
|
|
|
@ -30,7 +30,7 @@ class QWidget;
|
|||
class FeedReaderStringDefs
|
||||
{
|
||||
public:
|
||||
static bool showError(QWidget *parent, RsFeedAddResult result, const QString &title, const QString &text);
|
||||
static bool showError(QWidget *parent, RsFeedResult result, const QString &title, const QString &text);
|
||||
static QString workState(FeedInfo::WorkState state);
|
||||
static QString errorString(const FeedInfo &feedInfo);
|
||||
static QString errorString(RsFeedReaderErrorState errorState, const std::string &errorString);
|
||||
|
|
119
plugins/FeedReader/gui/FeedTreeWidget.cpp
Normal file
119
plugins/FeedReader/gui/FeedTreeWidget.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*******************************************************************************
|
||||
* plugins/FeedReader/gui/FeedTreeWidget.cpp *
|
||||
* *
|
||||
* Copyright (C) 2012 RetroShare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* 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 <QDropEvent>
|
||||
#include "FeedTreeWidget.h"
|
||||
|
||||
FeedTreeWidget::FeedTreeWidget(QWidget *parent) : RSTreeWidget(parent)
|
||||
{
|
||||
mDraggedItem = NULL;
|
||||
}
|
||||
|
||||
void FeedTreeWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
mDraggedItem = currentItem();
|
||||
RSTreeWidget::dragEnterEvent(event);
|
||||
}
|
||||
|
||||
void FeedTreeWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
||||
{
|
||||
RSTreeWidget::dragLeaveEvent(event);
|
||||
mDraggedItem = NULL;
|
||||
}
|
||||
|
||||
bool FeedTreeWidget::canDrop(QDropEvent *event, QTreeWidgetItem **dropItem)
|
||||
{
|
||||
if (dropItem) {
|
||||
*dropItem = NULL;
|
||||
}
|
||||
|
||||
if (!mDraggedItem) {
|
||||
/* no drag item */
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex droppedIndex = indexAt(event->pos());
|
||||
if (!droppedIndex.isValid()) {
|
||||
/* no drop target */
|
||||
return false;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *dropItemIntern = itemFromIndex(droppedIndex);
|
||||
if (!dropItemIntern) {
|
||||
/* no drop item */
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((dropItemIntern->flags() & Qt::ItemIsDropEnabled) == 0) {
|
||||
/* drop is disabled */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dropItemIntern == mDraggedItem->parent()) {
|
||||
/* drag item parent */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dropItem) {
|
||||
*dropItem = dropItemIntern;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FeedTreeWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
if (!canDrop(event)) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
RSTreeWidget::dragMoveEvent(event);
|
||||
}
|
||||
|
||||
void FeedTreeWidget::dropEvent(QDropEvent *event)
|
||||
{
|
||||
QTreeWidgetItem *dropItem;
|
||||
if (!canDrop(event, &dropItem)) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDraggedItem) {
|
||||
/* no drag item */
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *draggedParent = mDraggedItem->parent();
|
||||
if (!draggedParent) {
|
||||
/* no drag item parent */
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dropItem) {
|
||||
/* no drop item */
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
emit feedReparent(mDraggedItem, dropItem);
|
||||
}
|
50
plugins/FeedReader/gui/FeedTreeWidget.h
Normal file
50
plugins/FeedReader/gui/FeedTreeWidget.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
* plugins/FeedReader/gui/FeedTreeWidget.h *
|
||||
* *
|
||||
* Copyright (C) 2012 by Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _FEEDTREEWIDGET_H
|
||||
#define _FEEDTREEWIDGET_H
|
||||
|
||||
#include "gui/common/RSTreeWidget.h"
|
||||
|
||||
/* Subclassing RSTreeWidget */
|
||||
class FeedTreeWidget : public RSTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FeedTreeWidget(QWidget *parent = 0);
|
||||
|
||||
Q_SIGNALS:
|
||||
void feedReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent);
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragLeaveEvent(QDragLeaveEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
private:
|
||||
bool canDrop(QDropEvent *event, QTreeWidgetItem **dropItem = NULL);
|
||||
|
||||
private:
|
||||
QTreeWidgetItem *mDraggedItem;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -25,8 +25,13 @@
|
|||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
class RsFeedReader;
|
||||
class RsGxsForums;
|
||||
class RsPosted;
|
||||
class RsGxsForumGroup;
|
||||
class RsPostedGroup;
|
||||
extern RsFeedReader *rsFeedReader;
|
||||
|
||||
enum RsFeedReaderErrorState {
|
||||
|
@ -38,14 +43,20 @@ enum RsFeedReaderErrorState {
|
|||
RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE = 3,
|
||||
RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND = 4,
|
||||
RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE = 5,
|
||||
RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED = 6,
|
||||
|
||||
/* process */
|
||||
RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR = 50,
|
||||
RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT = 51,
|
||||
RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE = 100,
|
||||
// RS_FEED_ERRORSTATE_PROCESS_FORUM_CREATE = 100,
|
||||
RS_FEED_ERRORSTATE_PROCESS_FORUM_NOT_FOUND = 101,
|
||||
RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_ADMIN = 102,
|
||||
RS_FEED_ERRORSTATE_PROCESS_FORUM_NO_AUTHOR = 103,
|
||||
// RS_FEED_ERRORSTATE_PROCESS_POSTED_CREATE = 104,
|
||||
RS_FEED_ERRORSTATE_PROCESS_POSTED_NOT_FOUND = 105,
|
||||
RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_ADMIN = 106,
|
||||
RS_FEED_ERRORSTATE_PROCESS_POSTED_NO_AUTHOR = 107,
|
||||
RS_FEED_ERRORSTATE_PROCESS_POST = 108,
|
||||
|
||||
RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR = 150,
|
||||
RS_FEED_ERRORSTATE_PROCESS_XPATH_INTERNAL_ERROR = 151,
|
||||
|
@ -56,14 +67,14 @@ enum RsFeedReaderErrorState {
|
|||
RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT = 156
|
||||
};
|
||||
|
||||
enum RsFeedAddResult
|
||||
enum RsFeedResult
|
||||
{
|
||||
RS_FEED_ADD_RESULT_SUCCESS,
|
||||
RS_FEED_ADD_RESULT_FEED_NOT_FOUND,
|
||||
RS_FEED_ADD_RESULT_PARENT_NOT_FOUND,
|
||||
RS_FEED_ADD_RESULT_PARENT_IS_NO_FOLDER,
|
||||
RS_FEED_ADD_RESULT_FEED_IS_FOLDER,
|
||||
RS_FEED_ADD_RESULT_FEED_IS_NO_FOLDER
|
||||
RS_FEED_RESULT_SUCCESS,
|
||||
RS_FEED_RESULT_FEED_NOT_FOUND,
|
||||
RS_FEED_RESULT_PARENT_NOT_FOUND,
|
||||
RS_FEED_RESULT_PARENT_IS_NO_FOLDER,
|
||||
RS_FEED_RESULT_FEED_IS_FOLDER,
|
||||
RS_FEED_RESULT_FEED_IS_NO_FOLDER
|
||||
};
|
||||
|
||||
enum RsFeedTransformationType
|
||||
|
@ -102,6 +113,8 @@ public:
|
|||
flag.deactivated = false;
|
||||
flag.forum = false;
|
||||
flag.updateForumInfo = false;
|
||||
flag.posted = false;
|
||||
flag.updatePostedInfo = false;
|
||||
flag.embedImages = false;
|
||||
flag.saveCompletePage = false;
|
||||
flag.preview = false;
|
||||
|
@ -122,6 +135,7 @@ public:
|
|||
time_t lastUpdate;
|
||||
uint32_t storageTime;
|
||||
std::string forumId;
|
||||
std::string postedId;
|
||||
WorkState workstate;
|
||||
RsFeedReaderErrorState errorState;
|
||||
std::string errorString;
|
||||
|
@ -141,6 +155,11 @@ public:
|
|||
bool deactivated : 1;
|
||||
bool forum : 1;
|
||||
bool updateForumInfo : 1;
|
||||
bool posted : 1;
|
||||
bool updatePostedInfo : 1;
|
||||
bool postedFirstImage : 1;
|
||||
bool postedOnlyImage : 1;
|
||||
bool postedShrinkImage : 1;
|
||||
bool embedImages : 1;
|
||||
bool saveCompletePage : 1;
|
||||
bool preview : 1;
|
||||
|
@ -166,6 +185,9 @@ public:
|
|||
std::string description;
|
||||
std::string descriptionTransformed;
|
||||
time_t pubDate;
|
||||
std::string attachmentLink;
|
||||
std::vector<unsigned char> attachment;
|
||||
std::string attachmentMimeType;
|
||||
|
||||
struct {
|
||||
bool isnew : 1;
|
||||
|
@ -174,6 +196,32 @@ public:
|
|||
} flag;
|
||||
};
|
||||
|
||||
class FeedReaderOptimizeImageTask
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
POSTED,
|
||||
SIZE
|
||||
};
|
||||
|
||||
public:
|
||||
Type mType;
|
||||
std::vector<unsigned char> mImage;
|
||||
std::string mMimeType;
|
||||
std::vector<unsigned char> mImageResult;
|
||||
std::string mMimeTypeResult;
|
||||
bool mResult;
|
||||
|
||||
public:
|
||||
FeedReaderOptimizeImageTask(Type type, const std::vector<unsigned char> &image, const std::string &mimeType)
|
||||
{
|
||||
mType = type;
|
||||
mImage = image;
|
||||
mMimeType = mimeType;
|
||||
mResult = false;
|
||||
}
|
||||
};
|
||||
|
||||
class RsFeedReaderNotify
|
||||
{
|
||||
public:
|
||||
|
@ -181,6 +229,7 @@ public:
|
|||
|
||||
virtual void notifyFeedChanged(uint32_t /*feedId*/, int /*type*/) {}
|
||||
virtual void notifyMsgChanged(uint32_t /*feedId*/, const std::string &/*msgId*/, int /*type*/) {}
|
||||
virtual void notifyOptimizeImage() {}
|
||||
};
|
||||
|
||||
class RsFeedReader
|
||||
|
@ -201,10 +250,11 @@ public:
|
|||
virtual bool getSaveInBackground() = 0;
|
||||
virtual void setSaveInBackground(bool saveInBackground) = 0;
|
||||
|
||||
virtual RsFeedAddResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) = 0;
|
||||
virtual RsFeedAddResult setFolder(uint32_t feedId, const std::string &name) = 0;
|
||||
virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0;
|
||||
virtual RsFeedAddResult setFeed(uint32_t feedId, const FeedInfo &feedInfo) = 0;
|
||||
virtual RsFeedResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId) = 0;
|
||||
virtual RsFeedResult setFolder(uint32_t feedId, const std::string &name) = 0;
|
||||
virtual RsFeedResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0;
|
||||
virtual RsFeedResult setFeed(uint32_t feedId, const FeedInfo &feedInfo) = 0;
|
||||
virtual RsFeedResult setParent(uint32_t feedId, uint32_t parentId) = 0;
|
||||
virtual bool removeFeed(uint32_t feedId) = 0;
|
||||
virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId) = 0;
|
||||
virtual void getFeedList(uint32_t parentId, std::list<FeedInfo> &feedInfos) = 0;
|
||||
|
@ -220,6 +270,14 @@ public:
|
|||
virtual bool retransformMsg(uint32_t feedId, const std::string &msgId) = 0;
|
||||
virtual bool clearMessageCache(uint32_t feedId) = 0;
|
||||
|
||||
virtual RsGxsForums* forums() = 0;
|
||||
virtual RsPosted* posted() = 0;
|
||||
virtual bool getForumGroups(std::vector<RsGxsForumGroup> &groups, bool onlyOwn) = 0;
|
||||
virtual bool getPostedGroups(std::vector<RsPostedGroup> &groups, bool onlyOwn) = 0;
|
||||
|
||||
virtual FeedReaderOptimizeImageTask *getOptimizeImageTask() = 0;
|
||||
virtual void setOptimizeImageTaskResult(FeedReaderOptimizeImageTask *optimizeImageTask) = 0;
|
||||
|
||||
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString) = 0;
|
||||
virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString) = 0;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,32 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+79"/>
|
||||
<location line="+398"/>
|
||||
<source>Board</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+9"/>
|
||||
<source>Update board information</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<source>Only image</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<source>Use first image as board image</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<source>Shrink image</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-391"/>
|
||||
<source>Authentication (not yet supported)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -59,12 +84,12 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+121"/>
|
||||
<location line="+88"/>
|
||||
<source>Embed images</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-249"/>
|
||||
<location line="-216"/>
|
||||
<source>Storage time</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -99,22 +124,22 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-148"/>
|
||||
<location line="+200"/>
|
||||
<source>Type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+20"/>
|
||||
<location line="+24"/>
|
||||
<source>Forum</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+12"/>
|
||||
<location line="+10"/>
|
||||
<source>Local Feed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+239"/>
|
||||
<location line="-67"/>
|
||||
<source>Transformation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -129,7 +154,7 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+12"/>
|
||||
<location line="-58"/>
|
||||
<source>Misc</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -144,17 +169,17 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<location line="+100"/>
|
||||
<source>Update forum information</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+14"/>
|
||||
<location line="-86"/>
|
||||
<source>Save complete web page (experimental for local feeds)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-103"/>
|
||||
<location line="-70"/>
|
||||
<source>Description:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -164,18 +189,18 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+10"/>
|
||||
<location line="+17"/>
|
||||
<source>Name:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gui/AddFeedDialog.cpp" line="+77"/>
|
||||
<location filename="../gui/AddFeedDialog.cpp" line="+87"/>
|
||||
<source>Feed Details</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+142"/>
|
||||
<location line="+115"/>
|
||||
<location line="+211"/>
|
||||
<location line="+152"/>
|
||||
<location line="+15"/>
|
||||
<source>Edit feed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
@ -277,7 +302,7 @@
|
|||
<context>
|
||||
<name>FeedReaderDialog</name>
|
||||
<message>
|
||||
<location filename="../gui/FeedReaderDialog.ui" line="+91"/>
|
||||
<location filename="../gui/FeedReaderDialog.ui" line="+98"/>
|
||||
<source>Feeds</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -292,7 +317,7 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../gui/FeedReaderDialog.cpp" line="+92"/>
|
||||
<location filename="../gui/FeedReaderDialog.cpp" line="+101"/>
|
||||
<source>Message Folders</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -342,12 +367,12 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+195"/>
|
||||
<location line="+198"/>
|
||||
<source>No name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+210"/>
|
||||
<location line="+241"/>
|
||||
<source>Add new folder</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -398,11 +423,21 @@
|
|||
<source>Please enter a new name for the folder</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+61"/>
|
||||
<source>Move feed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+0"/>
|
||||
<source>Cannot move feed.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FeedReaderFeedItem</name>
|
||||
<message>
|
||||
<location filename="../gui/FeedReaderFeedItem.ui" line="+195"/>
|
||||
<location filename="../gui/FeedReaderFeedItem.ui" line="+197"/>
|
||||
<location filename="../gui/FeedReaderFeedItem.cpp" line="+116"/>
|
||||
<source>Expand</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
@ -500,7 +535,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<location line="+26"/>
|
||||
<location filename="../gui/FeedReaderMessageWidget.cpp" line="+113"/>
|
||||
<location filename="../gui/FeedReaderMessageWidget.cpp" line="+117"/>
|
||||
<source>Title</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -542,12 +577,22 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+122"/>
|
||||
<location line="+127"/>
|
||||
<source>The messages will be added to the forum</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+15"/>
|
||||
<location line="-3"/>
|
||||
<source>The messages will be added to the forum and the board</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+6"/>
|
||||
<source>The messages will be added to the board</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+17"/>
|
||||
<source>No name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -576,8 +621,18 @@
|
|||
<source>Remove</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<source>Add to forum</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+5"/>
|
||||
<source>Add to board</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+7"/>
|
||||
<source>Retransform</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -659,12 +714,12 @@
|
|||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<location line="+96"/>
|
||||
<location line="+114"/>
|
||||
<source>Unknown</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="-79"/>
|
||||
<location line="-97"/>
|
||||
<source>Internal download error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -688,6 +743,11 @@
|
|||
<source>Unknown response code</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>Download blocked</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+5"/>
|
||||
<source>Internal process error</source>
|
||||
|
@ -699,12 +759,7 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>Can't create forum</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<location line="+6"/>
|
||||
<source>Forum not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -718,6 +773,26 @@
|
|||
<source>Forum has no author</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+6"/>
|
||||
<source>Board not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>You are not admin of the board</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>Board has no author</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+3"/>
|
||||
<source>Some posts could not be created</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+4"/>
|
||||
<source>Can't read html</source>
|
||||
|
@ -790,7 +865,7 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+47"/>
|
||||
<location line="+55"/>
|
||||
<source>Name:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -825,7 +900,7 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+20"/>
|
||||
<location line="+28"/>
|
||||
<source>Title:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -33,11 +33,14 @@ class p3FeedReaderThread;
|
|||
|
||||
class RsGxsForums;
|
||||
struct RsGxsForumGroup;
|
||||
class RsPosted;
|
||||
struct RsPostedGroup;
|
||||
class RsGxsIfaceHelper;
|
||||
|
||||
class p3FeedReader : public RsPQIService, public RsFeedReader
|
||||
{
|
||||
public:
|
||||
p3FeedReader(RsPluginHandler *pgHandler, RsGxsForums *forums);
|
||||
p3FeedReader(RsPluginHandler *pgHandler, RsGxsForums *forums, RsPosted *posted);
|
||||
|
||||
/****************** FeedReader Interface *************/
|
||||
virtual void stop();
|
||||
|
@ -52,10 +55,11 @@ public:
|
|||
virtual bool getSaveInBackground();
|
||||
virtual void setSaveInBackground(bool saveInBackground);
|
||||
|
||||
virtual RsFeedAddResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId);
|
||||
virtual RsFeedAddResult setFolder(uint32_t feedId, const std::string &name);
|
||||
virtual RsFeedAddResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId);
|
||||
virtual RsFeedAddResult setFeed(uint32_t feedId, const FeedInfo &feedInfo);
|
||||
virtual RsFeedResult addFolder(uint32_t parentId, const std::string &name, uint32_t &feedId);
|
||||
virtual RsFeedResult setFolder(uint32_t feedId, const std::string &name);
|
||||
virtual RsFeedResult addFeed(const FeedInfo &feedInfo, uint32_t &feedId);
|
||||
virtual RsFeedResult setFeed(uint32_t feedId, const FeedInfo &feedInfo);
|
||||
virtual RsFeedResult setParent(uint32_t feedId, uint32_t parentId);
|
||||
virtual bool removeFeed(uint32_t feedId);
|
||||
virtual bool addPreviewFeed(const FeedInfo &feedInfo, uint32_t &feedId);
|
||||
virtual void getFeedList(uint32_t parentId, std::list<FeedInfo> &feedInfos);
|
||||
|
@ -71,6 +75,14 @@ public:
|
|||
virtual bool retransformMsg(uint32_t feedId, const std::string &msgId);
|
||||
virtual bool clearMessageCache(uint32_t feedId);
|
||||
|
||||
virtual RsGxsForums* forums() { return mForums; }
|
||||
virtual RsPosted* posted() { return mPosted; }
|
||||
virtual bool getForumGroups(std::vector<RsGxsForumGroup> &groups, bool onlyOwn);
|
||||
virtual bool getPostedGroups(std::vector<RsPostedGroup> &groups, bool onlyOwn);
|
||||
|
||||
virtual FeedReaderOptimizeImageTask *getOptimizeImageTask();
|
||||
virtual void setOptimizeImageTaskResult(FeedReaderOptimizeImageTask *optimizeImageTask);
|
||||
|
||||
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
||||
virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString);
|
||||
|
||||
|
@ -83,7 +95,7 @@ public:
|
|||
void onDownloadSuccess(uint32_t feedId, const std::string &content, std::string &icon);
|
||||
void onDownloadError(uint32_t feedId, RsFeedReaderErrorState result, const std::string &errorString);
|
||||
void onProcessSuccess_filterMsg(uint32_t feedId, std::list<RsFeedReaderMsg*> &msgs);
|
||||
void onProcessSuccess_addMsgs(uint32_t feedId, std::list<RsFeedReaderMsg*> &msgs, bool single);
|
||||
void onProcessSuccess_addMsgs(uint32_t feedId, std::list<RsFeedReaderMsg*> &msgs);
|
||||
void onProcessError(uint32_t feedId, RsFeedReaderErrorState result, const std::string &errorString);
|
||||
|
||||
bool getFeedToProcess(RsFeedReaderFeed &feed, uint32_t neededFeedId);
|
||||
|
@ -92,7 +104,10 @@ public:
|
|||
|
||||
bool getForumGroup(const RsGxsGroupId &groupId, RsGxsForumGroup &forumGroup);
|
||||
bool updateForumGroup(const RsGxsForumGroup &forumGroup, const std::string &groupName, const std::string &groupDescription);
|
||||
bool waitForToken(uint32_t token);
|
||||
bool getPostedGroup(const RsGxsGroupId &groupId, RsPostedGroup &postedGroup);
|
||||
bool updatePostedGroup(const RsPostedGroup &postedGroup, const std::string &groupName, const std::string &groupDescription);
|
||||
bool waitForToken(RsGxsIfaceHelper *interface, uint32_t token);
|
||||
bool optimizeImage(FeedReaderOptimizeImageTask::Type type, const std::vector<unsigned char> &image, const std::string &mimeType, std::vector<unsigned char> &resultImage, std::string &resultMimeType);
|
||||
|
||||
protected:
|
||||
/****************** p3Config STUFF *******************/
|
||||
|
@ -109,6 +124,7 @@ private:
|
|||
private:
|
||||
time_t mLastClean;
|
||||
RsGxsForums *mForums;
|
||||
RsPosted *mPosted;
|
||||
RsFeedReaderNotify *mNotify;
|
||||
volatile bool mStopped;
|
||||
|
||||
|
@ -133,6 +149,10 @@ private:
|
|||
RsMutex mProcessMutex;
|
||||
std::list<uint32_t> mProcessFeeds;
|
||||
|
||||
RsMutex mImageMutex;
|
||||
std::list<FeedReaderOptimizeImageTask*> mImages;
|
||||
std::list<FeedReaderOptimizeImageTask*> mResultImages;
|
||||
|
||||
RsMutex mPreviewMutex;
|
||||
p3FeedReaderThread *mPreviewDownloadThread;
|
||||
p3FeedReaderThread *mPreviewProcessThread;
|
||||
|
|
|
@ -89,7 +89,7 @@ void p3FeedReaderThread::threadTick()
|
|||
/* first, filter the messages */
|
||||
mFeedReader->onProcessSuccess_filterMsg(feed.feedId, msgs);
|
||||
if (isRunning()) {
|
||||
/* second, process the descriptions */
|
||||
/* second, process the descriptions and attachment */
|
||||
for (it = msgs.begin(); it != msgs.end(); ) {
|
||||
if (!isRunning()) {
|
||||
break;
|
||||
|
@ -107,7 +107,7 @@ void p3FeedReaderThread::threadTick()
|
|||
|
||||
std::list<RsFeedReaderMsg*> msgSingle;
|
||||
msgSingle.push_back(mi);
|
||||
mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgSingle, true);
|
||||
mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgSingle);
|
||||
|
||||
/* delete not accepted message */
|
||||
std::list<RsFeedReaderMsg*>::iterator it1;
|
||||
|
@ -122,15 +122,18 @@ void p3FeedReaderThread::threadTick()
|
|||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (!feed.preview) {
|
||||
if (isRunning()) {
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
/* third, add messages */
|
||||
mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgs, false);
|
||||
mFeedReader->onProcessSuccess_addMsgs(feed.feedId, msgs);
|
||||
} else {
|
||||
mFeedReader->onProcessError(feed.feedId, result, errorString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mFeedReader->onProcessError(feed.feedId, result, errorString);
|
||||
}
|
||||
|
@ -150,12 +153,12 @@ void p3FeedReaderThread::threadTick()
|
|||
/****************************** Download ***********************************/
|
||||
/***************************************************************************/
|
||||
|
||||
static bool isContentType(const std::string &contentType, const char *type)
|
||||
bool p3FeedReaderThread::isContentType(const std::string &contentType, const char *type)
|
||||
{
|
||||
return (strncasecmp(contentType.c_str(), type, strlen(type)) == 0);
|
||||
}
|
||||
|
||||
static bool toBase64(const std::vector<unsigned char> &data, std::string &base64)
|
||||
bool p3FeedReaderThread::toBase64(const std::vector<unsigned char> &data, std::string &base64)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
@ -184,6 +187,28 @@ static bool toBase64(const std::vector<unsigned char> &data, std::string &base64
|
|||
return result;
|
||||
}
|
||||
|
||||
bool p3FeedReaderThread::fromBase64(const std::string &base64, std::vector<unsigned char> &data)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
BIO *b64 = BIO_new(BIO_f_base64());
|
||||
if (b64) {
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||
BIO *source = BIO_new_mem_buf(base64.c_str(), -1); // read-only source
|
||||
if (source) {
|
||||
BIO_push(b64, source);
|
||||
const int maxlen = base64.length() / 4 * 3 + 1;
|
||||
data.resize(maxlen);
|
||||
const int len = BIO_read(b64, data.data(), maxlen);
|
||||
data.resize(len);
|
||||
result = true;
|
||||
}
|
||||
BIO_free_all(b64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string getBaseLink(std::string link)
|
||||
{
|
||||
size_t found = link.rfind('/');
|
||||
|
@ -196,7 +221,7 @@ static std::string getBaseLink(std::string link)
|
|||
|
||||
static std::string calculateLink(const std::string &baseLink, const std::string &link)
|
||||
{
|
||||
if (link.substr(0, 7) == "http://") {
|
||||
if (link.substr(0, 7) == "http://" || link.substr(0, 8) == "https://") {
|
||||
/* absolute link */
|
||||
return link;
|
||||
}
|
||||
|
@ -204,8 +229,14 @@ static std::string calculateLink(const std::string &baseLink, const std::string
|
|||
/* calculate link of base link */
|
||||
std::string resultLink = baseLink;
|
||||
|
||||
/* link should begin with "http://" */
|
||||
if (resultLink.substr(0, 7) != "http://") {
|
||||
int hostStart = 0;
|
||||
/* link should begin with "http://" or "https://" */
|
||||
if (resultLink.substr(0, 7) == "http://") {
|
||||
hostStart = 7;
|
||||
} else if (resultLink.substr(0, 8) == "https://") {
|
||||
hostStart = 8;
|
||||
} else {
|
||||
hostStart = 7;
|
||||
resultLink.insert(0, "http://");
|
||||
}
|
||||
|
||||
|
@ -216,7 +247,7 @@ static std::string calculateLink(const std::string &baseLink, const std::string
|
|||
|
||||
if (*link.begin() == '/') {
|
||||
/* link begins with "/" */
|
||||
size_t found = resultLink.find('/', 7);
|
||||
size_t found = resultLink.find('/', hostStart);
|
||||
if (found != std::string::npos) {
|
||||
resultLink.erase(found);
|
||||
}
|
||||
|
@ -245,12 +276,12 @@ static bool getFavicon(CURLWrapper &CURL, const std::string &url, std::string &i
|
|||
if (code == CURLE_OK) {
|
||||
if (CURL.responseCode() == 200) {
|
||||
std::string contentType = CURL.contentType();
|
||||
if (isContentType(contentType, "image/x-icon") ||
|
||||
isContentType(contentType, "application/octet-stream") ||
|
||||
isContentType(contentType, "text/plain")) {
|
||||
if (p3FeedReaderThread::isContentType(contentType, "image/") ||
|
||||
p3FeedReaderThread::isContentType(contentType, "application/octet-stream") ||
|
||||
p3FeedReaderThread::isContentType(contentType, "text/plain")) {
|
||||
if (!vicon.empty()) {
|
||||
#warning p3FeedReaderThread.cc TODO thunder2: check it
|
||||
result = toBase64(vicon, icon);
|
||||
result = p3FeedReaderThread::toBase64(vicon, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,6 +327,9 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_BLOCKED;
|
||||
break;
|
||||
case 404:
|
||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_NOT_FOUND;
|
||||
break;
|
||||
|
@ -814,6 +848,22 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
|||
|
||||
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;
|
||||
if (xml.readXML(feed.content.c_str())) {
|
||||
xmlNodePtr root = xml.getRootElement();
|
||||
|
@ -959,6 +1009,26 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
|||
item->pubDate = time(NULL);
|
||||
}
|
||||
|
||||
if (feedFormat == FORMAT_RSS) {
|
||||
/* <enclosure url="" type=""></enclosure> */
|
||||
xmlNodePtr enclosure = xml.findNode(node->children, "enclosure", false);
|
||||
if (enclosure) {
|
||||
std::string enclosureMimeType = xml.getAttr(enclosure, "type");
|
||||
std::string enclosureUrl = xml.getAttr(enclosure, "url");
|
||||
if (!enclosureUrl.empty()) {
|
||||
item->attachmentLink = enclosureUrl;
|
||||
item->attachmentMimeType = enclosureMimeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minimumPubDate) {
|
||||
if (item->pubDate < minimumPubDate) {
|
||||
// pubDate is less than storage time, don't add as new item
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
entries.push_back(item);
|
||||
}
|
||||
} else {
|
||||
|
@ -1013,10 +1083,44 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||
std::string proxy = getProxyForFeed(feed);
|
||||
|
||||
/* attachment */
|
||||
if (!msg->attachmentLink.empty()) {
|
||||
if (isContentType(msg->attachmentMimeType, "image/")) {
|
||||
CURLWrapper CURL(proxy);
|
||||
CURLcode code = CURL.downloadBinary(msg->attachmentLink, msg->attachmentBinary);
|
||||
if (code == CURLE_OK && CURL.responseCode() == 200) {
|
||||
std::string contentType = CURL.contentType();
|
||||
if (isContentType(contentType, "image/")) {
|
||||
msg->attachmentBinaryMimeType = contentType;
|
||||
|
||||
bool forum = (feed.flag & RS_FEED_FLAG_FORUM) && !feed.preview;
|
||||
bool posted = (feed.flag & RS_FEED_FLAG_POSTED) && !feed.preview;
|
||||
|
||||
if (!forum && ! posted) {
|
||||
/* no need to optimize image */
|
||||
std::vector<unsigned char> optimizedBinary;
|
||||
std::string optimizedMimeType;
|
||||
if (mFeedReader->optimizeImage(FeedReaderOptimizeImageTask::SIZE, msg->attachmentBinary, msg->attachmentBinaryMimeType, optimizedBinary, optimizedMimeType)) {
|
||||
if (toBase64(optimizedBinary, msg->attachment)) {
|
||||
msg->attachmentMimeType = optimizedMimeType;
|
||||
} else {
|
||||
msg->attachment.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msg->attachmentBinary.clear();
|
||||
}
|
||||
} else {
|
||||
msg->attachmentBinary.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string url;
|
||||
if (feed.flag & RS_FEED_FLAG_SAVE_COMPLETE_PAGE) {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download page " << msg->link << std::endl;
|
||||
#endif
|
||||
std::string content;
|
||||
CURLWrapper CURL(proxy);
|
||||
|
@ -1053,7 +1157,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
|
||||
if (result != RS_FEED_ERRORSTATE_OK) {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot download page, CURLCode = " << code << ", error = " << errorString << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -1070,12 +1174,19 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
|
||||
if (isRunning()) {
|
||||
/* process description */
|
||||
bool processPostedFirstImage = (feed.flag & RS_FEED_FLAG_POSTED_FIRST_IMAGE) ? true : false;
|
||||
if (!msg->attachmentBinary.empty()) {
|
||||
/* use attachment as image */
|
||||
processPostedFirstImage = false;
|
||||
}
|
||||
|
||||
//long todo; // encoding
|
||||
HTMLWrapper html;
|
||||
if (html.readHTML(msg->description.c_str(), url.c_str())) {
|
||||
xmlNodePtr root = html.getRootElement();
|
||||
if (root) {
|
||||
std::list<xmlNodePtr> nodesToDelete;
|
||||
xmlNodePtr postedFirstImageNode = NULL;
|
||||
|
||||
/* process all children */
|
||||
std::list<xmlNodePtr> nodes;
|
||||
|
@ -1192,7 +1303,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
if (!src.empty()) {
|
||||
/* download image */
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") download image " << src << std::endl;
|
||||
#endif
|
||||
std::vector<unsigned char> data;
|
||||
CURLWrapper CURL(proxy);
|
||||
|
@ -1200,15 +1311,25 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
if (code == CURLE_OK && CURL.responseCode() == 200) {
|
||||
std::string contentType = CURL.contentType();
|
||||
if (isContentType(contentType, "image/")) {
|
||||
std::vector<unsigned char> optimizedData;
|
||||
std::string optimizedMimeType;
|
||||
if (mFeedReader->optimizeImage(FeedReaderOptimizeImageTask::SIZE, data, contentType, optimizedData, optimizedMimeType)) {
|
||||
std::string base64;
|
||||
if (toBase64(data, base64)) {
|
||||
if (toBase64(optimizedData, base64)) {
|
||||
std::string imageBase64;
|
||||
rs_sprintf(imageBase64, "data:%s;base64,%s", contentType.c_str(), base64.c_str());
|
||||
rs_sprintf(imageBase64, "data:%s;base64,%s", optimizedMimeType.c_str(), base64.c_str());
|
||||
if (html.setAttr(node, "src", imageBase64.c_str())) {
|
||||
removeImage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (processPostedFirstImage && postedFirstImageNode == NULL) {
|
||||
/* set first image */
|
||||
msg->postedFirstImage = data;
|
||||
msg->postedFirstImageMimeType = contentType;
|
||||
postedFirstImageNode = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1241,10 +1362,25 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
if (isRunning()) {
|
||||
if (!html.saveHTML(msg->description)) {
|
||||
if (html.saveHTML(msg->description)) {
|
||||
if (postedFirstImageNode) {
|
||||
/* Remove first image and create description without the image */
|
||||
xmlUnlinkNode(postedFirstImageNode);
|
||||
xmlFreeNode(postedFirstImageNode);
|
||||
|
||||
if (!html.saveHTML(msg->postedDescriptionWithoutFirstImage)) {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
|
@ -1253,14 +1389,14 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
}
|
||||
} else {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") no root element" << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
} else {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::processMsg - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
|
|
|
@ -54,6 +54,11 @@ public:
|
|||
static RsFeedReaderErrorState processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString);
|
||||
|
||||
static RsFeedReaderErrorState processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
||||
|
||||
static bool isContentType(const std::string &contentType, const char *type);
|
||||
static bool toBase64(const std::vector<unsigned char> &data, std::string &base64);
|
||||
static bool fromBase64(const std::string &base64, std::vector<unsigned char> &data);
|
||||
|
||||
private:
|
||||
virtual void threadTick() override; /// @see RsTickingThread
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ void RsFeedReaderFeed::clear()
|
|||
storageTime = 0;
|
||||
flag = 0;
|
||||
forumId.clear();
|
||||
postedId.clear();
|
||||
description.clear();
|
||||
icon.clear();
|
||||
errorState = RS_FEED_ERRORSTATE_OK;
|
||||
|
@ -85,6 +86,7 @@ uint32_t RsFeedReaderSerialiser::sizeFeed(RsFeedReaderFeed *item)
|
|||
s += item->xpathsToUse.TlvSize();
|
||||
s += item->xpathsToRemove.TlvSize();
|
||||
s += GetTlvStringSize(item->xslt);
|
||||
s += GetTlvStringSize(item->postedId);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -108,7 +110,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
|||
offset += 8;
|
||||
|
||||
/* add values */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 2); /* version */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 3); /* version */
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->feedId);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->parentId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url);
|
||||
|
@ -124,6 +126,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
|||
ok &= setRawUInt32(data, tlvsize, &offset, item->storageTime);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->flag);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->postedId);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->errorState);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->transformationType);
|
||||
|
@ -208,6 +211,9 @@ RsFeedReaderFeed *RsFeedReaderSerialiser::deserialiseFeed(void *data, uint32_t *
|
|||
ok &= getRawUInt32(data, rssize, &offset, &(item->storageTime));
|
||||
ok &= getRawUInt32(data, rssize, &offset, &(item->flag));
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->forumId);
|
||||
if (version >= 3) {
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->postedId);
|
||||
}
|
||||
uint32_t errorState = 0;
|
||||
ok &= getRawUInt32(data, rssize, &offset, &errorState);
|
||||
item->errorState = (RsFeedReaderErrorState) errorState;
|
||||
|
@ -268,6 +274,9 @@ void RsFeedReaderMsg::clear()
|
|||
descriptionTransformed.clear();
|
||||
pubDate = 0;
|
||||
flag = 0;
|
||||
attachmentLink.clear();
|
||||
attachment.clear();
|
||||
attachmentMimeType.clear();
|
||||
}
|
||||
|
||||
std::ostream &RsFeedReaderMsg::print(std::ostream &out, uint16_t /*indent*/)
|
||||
|
@ -288,6 +297,9 @@ uint32_t RsFeedReaderSerialiser::sizeMsg(RsFeedReaderMsg *item)
|
|||
s += GetTlvStringSize(item->descriptionTransformed);
|
||||
s += sizeof(uint32_t); /* pubDate */
|
||||
s += sizeof(uint32_t); /* flag */
|
||||
s += GetTlvStringSize(item->attachmentLink);
|
||||
s += GetTlvStringSize(item->attachment);
|
||||
s += GetTlvStringSize(item->attachmentMimeType);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -311,7 +323,7 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin
|
|||
offset += 8;
|
||||
|
||||
/* add values */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 2); /* version */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 3); /* version */
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->feedId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title);
|
||||
|
@ -321,6 +333,9 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin
|
|||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->flag);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LOCATION, item->attachmentLink);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PIC_AUTH, item->attachment);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PIC_TYPE, item->attachmentMimeType);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
|
@ -384,6 +399,11 @@ RsFeedReaderMsg *RsFeedReaderSerialiser::deserialiseMsg(void *data, uint32_t *pk
|
|||
}
|
||||
ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate));
|
||||
ok &= getRawUInt32(data, rssize, &offset, &(item->flag));
|
||||
if (version >= 3) {
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LOCATION, item->attachmentLink);
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PIC_AUTH, item->attachment);
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PIC_TYPE, item->attachmentMimeType);
|
||||
}
|
||||
|
||||
if (offset != rssize)
|
||||
{
|
||||
|
|
|
@ -34,17 +34,22 @@ const uint8_t RS_PKT_SUBTYPE_FEEDREADER_MSG = 0x03;
|
|||
|
||||
/**************************************************************************/
|
||||
|
||||
#define RS_FEED_FLAG_FOLDER 0x001
|
||||
#define RS_FEED_FLAG_INFO_FROM_FEED 0x002
|
||||
#define RS_FEED_FLAG_STANDARD_STORAGE_TIME 0x004
|
||||
#define RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL 0x008
|
||||
#define RS_FEED_FLAG_STANDARD_PROXY 0x010
|
||||
#define RS_FEED_FLAG_AUTHENTICATION 0x020
|
||||
#define RS_FEED_FLAG_DEACTIVATED 0x040
|
||||
#define RS_FEED_FLAG_FORUM 0x080
|
||||
#define RS_FEED_FLAG_UPDATE_FORUM_INFO 0x100
|
||||
#define RS_FEED_FLAG_EMBED_IMAGES 0x200
|
||||
#define RS_FEED_FLAG_SAVE_COMPLETE_PAGE 0x400
|
||||
#define RS_FEED_FLAG_FOLDER 0x0001
|
||||
#define RS_FEED_FLAG_INFO_FROM_FEED 0x0002
|
||||
#define RS_FEED_FLAG_STANDARD_STORAGE_TIME 0x0004
|
||||
#define RS_FEED_FLAG_STANDARD_UPDATE_INTERVAL 0x0008
|
||||
#define RS_FEED_FLAG_STANDARD_PROXY 0x0010
|
||||
#define RS_FEED_FLAG_AUTHENTICATION 0x0020
|
||||
#define RS_FEED_FLAG_DEACTIVATED 0x0040
|
||||
#define RS_FEED_FLAG_FORUM 0x0080
|
||||
#define RS_FEED_FLAG_UPDATE_FORUM_INFO 0x0100
|
||||
#define RS_FEED_FLAG_EMBED_IMAGES 0x0200
|
||||
#define RS_FEED_FLAG_SAVE_COMPLETE_PAGE 0x0400
|
||||
#define RS_FEED_FLAG_POSTED 0x0800
|
||||
#define RS_FEED_FLAG_UPDATE_POSTED_INFO 0x1000
|
||||
#define RS_FEED_FLAG_POSTED_FIRST_IMAGE 0x2000
|
||||
#define RS_FEED_FLAG_POSTED_ONLY_IMAGE 0x4000
|
||||
#define RS_FEED_FLAG_POSTED_SHRINK_IMAGE 0x8000
|
||||
|
||||
class RsFeedReaderFeed : public RsItem
|
||||
{
|
||||
|
@ -62,6 +67,7 @@ public:
|
|||
virtual ~RsFeedReaderFeed() {}
|
||||
|
||||
virtual void clear();
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob, RsGenericSerializer::SerializeContext&) {}
|
||||
|
||||
uint32_t feedId;
|
||||
uint32_t parentId;
|
||||
|
@ -75,6 +81,7 @@ public:
|
|||
time_t lastUpdate;
|
||||
uint32_t flag; // RS_FEED_FLAG_...
|
||||
std::string forumId;
|
||||
std::string postedId;
|
||||
uint32_t storageTime;
|
||||
std::string description;
|
||||
std::string icon;
|
||||
|
@ -105,6 +112,7 @@ public:
|
|||
virtual ~RsFeedReaderMsg() {}
|
||||
|
||||
virtual void clear();
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob, RsGenericSerializer::SerializeContext&) {}
|
||||
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
std::string msgId;
|
||||
|
@ -116,6 +124,16 @@ public:
|
|||
std::string descriptionTransformed;
|
||||
time_t pubDate;
|
||||
uint32_t flag; // RS_FEEDMSG_FLAG_...
|
||||
std::string attachmentLink;
|
||||
std::string attachment; // binary as base64
|
||||
std::string attachmentMimeType;
|
||||
|
||||
// Only in memory when receiving messages
|
||||
std::vector<unsigned char> attachmentBinary;
|
||||
std::string attachmentBinaryMimeType;
|
||||
std::vector<unsigned char> postedFirstImage;
|
||||
std::string postedFirstImageMimeType;
|
||||
std::string postedDescriptionWithoutFirstImage;
|
||||
};
|
||||
|
||||
class RsFeedReaderSerialiser: public RsSerialType
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "CURLWrapper.h"
|
||||
#include <string.h>
|
||||
|
||||
#define USERAGENT "Mozilla/5.0 (rv:109.0) Gecko/20100101 Firefox/112.0"
|
||||
|
||||
CURLWrapper::CURLWrapper(const std::string &proxy)
|
||||
{
|
||||
mCurl = curl_easy_init();
|
||||
|
@ -65,6 +67,7 @@ CURLcode CURLWrapper::downloadText(const std::string &link, std::string &data)
|
|||
curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, writeFunctionString);
|
||||
curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_easy_setopt(mCurl, CURLOPT_USERAGENT, USERAGENT);
|
||||
|
||||
return curl_easy_perform(mCurl);
|
||||
}
|
||||
|
@ -94,6 +97,8 @@ CURLcode CURLWrapper::downloadBinary(const std::string &link, std::vector<unsign
|
|||
curl_easy_setopt(mCurl, CURLOPT_URL, link.c_str());
|
||||
curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, writeFunctionBinary);
|
||||
curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_easy_setopt(mCurl, CURLOPT_USERAGENT, USERAGENT);
|
||||
|
||||
return curl_easy_perform(mCurl);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ linux-* {
|
|||
PKGCONFIG += speex speexdsp
|
||||
} else {
|
||||
LIBS += -lspeex -lspeexdsp -lavcodec -lavutil
|
||||
|
||||
win32:isEmpty(QMAKE_SH) {
|
||||
# MinGW
|
||||
LIBS += -lbcrypt
|
||||
}
|
||||
}
|
||||
|
||||
#################################### Windows #####################################
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "util/rsbase64.h"
|
||||
#include "util/radix64.h"
|
||||
|
||||
#include "crypto/hashstream.h"
|
||||
|
||||
#include "pgp/pgpkeyutil.h"
|
||||
#include "pgp/rscertificate.h"
|
||||
#include "pgp/openpgpsdkhandler.h"
|
||||
|
@ -60,7 +62,7 @@ void FriendServer::threadTick()
|
|||
if(last_debugprint_TS + DELAY_BETWEEN_TWO_DEBUG_PRINT < now)
|
||||
{
|
||||
last_debugprint_TS = now;
|
||||
debugPrint();
|
||||
debugPrint(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,39 +77,80 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
|||
|
||||
// First of all, read PGP key and short invites, parse them, and check that they contain the same information
|
||||
|
||||
std::map<RsPeerId,PeerInfo>::iterator pi = handleIncomingClientData(item->pgp_public_key_b64,item->short_invite);
|
||||
RsPeerId pid;
|
||||
|
||||
// No need to test for it==mCurrentClients.end() because it will be directly caught by the exception handling below even before.
|
||||
// Respond with a list of potential friends
|
||||
if(!handleIncomingClientData(item->pgp_public_key_b64,item->short_invite,pid))
|
||||
{
|
||||
RsErr() << "Client data is dropped because of error." ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// All good.
|
||||
|
||||
auto pi(mCurrentClientPeers.find(pid));
|
||||
|
||||
// Update the list of closest peers for other peers, based on which known friends it reports, and of current peer depending
|
||||
// on friendship levels of other peers.
|
||||
|
||||
updateClosestPeers(pi->first,pi->second.pgp_fingerprint,item->already_received_peers);
|
||||
|
||||
RsDbg() << "Sending response item to " << item->PeerId() ;
|
||||
|
||||
RsFriendServerServerResponseItem *sr_item = new RsFriendServerServerResponseItem;
|
||||
RsFriendServerServerResponseItem sr_item;
|
||||
|
||||
std::map<RsPeerId,RsPgpFingerprint> friends;
|
||||
sr_item->nonce = pi->second.last_nonce;
|
||||
sr_item->friend_invites = computeListOfFriendInvites(item->n_requested_friends,pi->first,friends);
|
||||
sr_item->PeerId(item->PeerId());
|
||||
std::set<RsPeerId> friends;
|
||||
sr_item.unique_identifier = pi->second.last_identifier;
|
||||
sr_item.friend_invites = computeListOfFriendInvites(pi->first,item->n_requested_friends,item->already_received_peers,friends);
|
||||
sr_item.PeerId(item->PeerId());
|
||||
|
||||
// Update the have_added_as_friend for the list of each peer. We do that before sending because sending destroys
|
||||
// the item.
|
||||
RsDbg() << " Got " << sr_item.friend_invites.size() << " closest peers not in the list." ;
|
||||
RsDbg() << " Updating local information for destination peer." ;
|
||||
|
||||
for(const auto& pid:friends)
|
||||
// Update friendship levels of the peer that will receive the new list
|
||||
|
||||
for(auto fr:friends)
|
||||
{
|
||||
auto& p(mCurrentClientPeers[pid.first]);
|
||||
p.have_added_this_peer[computePeerDistance(p.pgp_fingerprint, pi->second.pgp_fingerprint)] = pi->first;
|
||||
auto& p(pi->second.friendship_levels[fr]);
|
||||
|
||||
RsDbg() << " Already a friend: " << fr << ", with local status " << static_cast<int>(p) ;
|
||||
|
||||
if(static_cast<int>(p) < static_cast<int>(RsFriendServer::PeerFriendshipLevel::HAS_KEY))
|
||||
{
|
||||
p = RsFriendServer::PeerFriendshipLevel::HAS_KEY;
|
||||
RsDbg() << " --> updating status to HAS_KEY" ;
|
||||
}
|
||||
}
|
||||
|
||||
// Now encrypt the item with the public PGP key of the destination. This prevents the wrong person to request for
|
||||
// someone else's data.
|
||||
#warning TODO
|
||||
|
||||
RsDbg() << " Encrypting item..." ;
|
||||
|
||||
RsFriendServerEncryptedServerResponseItem *encrypted_response_item = new RsFriendServerEncryptedServerResponseItem;
|
||||
uint32_t serialized_clear_size = FsSerializer().size(&sr_item);
|
||||
RsTemporaryMemory serialized_clear_mem(serialized_clear_size);
|
||||
FsSerializer().serialise(&sr_item,serialized_clear_mem,&serialized_clear_size);
|
||||
|
||||
uint32_t encrypted_mem_size = serialized_clear_size+1000; // leave some extra space
|
||||
RsTemporaryMemory encrypted_mem(encrypted_mem_size);
|
||||
|
||||
if(!mPgpHandler->encryptDataBin(PGPHandler::pgpIdFromFingerprint(pi->second.pgp_fingerprint),
|
||||
serialized_clear_mem,serialized_clear_size,
|
||||
encrypted_mem,&encrypted_mem_size))
|
||||
{
|
||||
RsErr() << "Cannot encrypt item for PGP Id/FPR " << pi->second.pgp_fingerprint << ". Something went wrong." ;
|
||||
return;
|
||||
}
|
||||
encrypted_response_item->PeerId(item->PeerId());
|
||||
encrypted_response_item->bin_len = encrypted_mem_size;
|
||||
encrypted_response_item->bin_data = malloc(encrypted_mem_size);
|
||||
|
||||
memcpy(encrypted_response_item->bin_data,encrypted_mem,encrypted_mem_size);
|
||||
|
||||
// Send the item.
|
||||
mni->SendItem(sr_item);
|
||||
|
||||
// Update the list of closest peers for all peers currently in the database.
|
||||
|
||||
updateClosestPeers(pi->first,pi->second.pgp_fingerprint);
|
||||
RsDbg() << " Sending item..." ;
|
||||
mni->SendItem(encrypted_response_item);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
@ -121,11 +164,14 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
|||
}
|
||||
}
|
||||
|
||||
std::map<std::string, bool> FriendServer::computeListOfFriendInvites(uint32_t nb_reqs_invites, const RsPeerId &pid, std::map<RsPeerId,RsPgpFingerprint>& friends)
|
||||
std::map<std::string,RsFriendServer::PeerFriendshipLevel> FriendServer::computeListOfFriendInvites(const RsPeerId &pid, uint32_t nb_reqs_invites,
|
||||
const std::map<RsPeerId,RsFriendServer::PeerFriendshipLevel>& already_known_peers,
|
||||
std::set<RsPeerId>& chosen_peers) const
|
||||
{
|
||||
// Strategy: we want to return the same set of friends for a given PGP profile key.
|
||||
// Still, using some closest distance strategy, the n-closest peers for profile A is not the
|
||||
// same set than the n-closest peers for profile B. We have multiple options:
|
||||
// same set than the n-closest peers for profile B, so some peers will not be in both sets.
|
||||
// We have multiple options:
|
||||
//
|
||||
// Option 1:
|
||||
//
|
||||
|
@ -145,38 +191,54 @@ std::map<std::string, bool> FriendServer::computeListOfFriendInvites(uint32_t nb
|
|||
//
|
||||
// So we choose Option 2.
|
||||
|
||||
std::map<std::string,bool> res;
|
||||
std::map<std::string,RsFriendServer::PeerFriendshipLevel> res;
|
||||
chosen_peers.clear();
|
||||
auto pinfo_it(mCurrentClientPeers.find(pid));
|
||||
|
||||
auto add_from = [&res,&friends,nb_reqs_invites,this](bool added,const std::map<PeerInfo::PeerDistance,RsPeerId>& lst) -> bool
|
||||
if(pinfo_it == mCurrentClientPeers.end())
|
||||
{
|
||||
for(const auto& pid:lst)
|
||||
{
|
||||
const auto p = mCurrentClientPeers.find(pid.second);
|
||||
res.insert(std::make_pair(p->second.short_certificate,added));
|
||||
friends.insert(std::make_pair(p->first,p->second.pgp_fingerprint));
|
||||
|
||||
if(res.size() >= nb_reqs_invites)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto& pinfo(mCurrentClientPeers[pid]);
|
||||
|
||||
// First add from peers who already added the current peer as friend, and leave if we already have enough
|
||||
|
||||
if(add_from(true,pinfo.have_added_this_peer))
|
||||
RsErr() << "inconsistency in computeListOfFriendInvites. Something's wrong in the code." ;
|
||||
return res;
|
||||
}
|
||||
auto pinfo(pinfo_it->second);
|
||||
|
||||
add_from(false,pinfo.closest_peers);
|
||||
for(const auto& pit:pinfo.closest_peers)
|
||||
{
|
||||
if(already_known_peers.find(pit.second) == already_known_peers.end())
|
||||
{
|
||||
RsDbg() << " peer " << pit.second << ": not in supplied list => adding it.";
|
||||
|
||||
const auto p = mCurrentClientPeers.find(pit.second);
|
||||
|
||||
if(p == mCurrentClientPeers.end()) // should not happen, but just an extra security.
|
||||
continue;
|
||||
|
||||
auto pp = p->second.friendship_levels.find(pid);
|
||||
|
||||
auto peer_friendship_level = (pp==p->second.friendship_levels.end())?(RsFriendServer::PeerFriendshipLevel::UNKNOWN):(pp->second);
|
||||
|
||||
res[p->second.short_certificate] = peer_friendship_level;
|
||||
chosen_peers.insert(p->first);
|
||||
|
||||
if(res.size() + already_known_peers.size() >= nb_reqs_invites)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto p = already_known_peers.find(pit.second);
|
||||
RsDbg() << " peer " << pit.second << ": already in supplied list, with status " << static_cast<int>(p->second) << ". Not adding it.";
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::map<RsPeerId,PeerInfo>::iterator FriendServer::handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64)
|
||||
bool FriendServer::handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64,RsPeerId& pid)
|
||||
{
|
||||
// 1 - Check that the incoming data is sound.
|
||||
|
||||
try
|
||||
{
|
||||
RsDbg() << " Checking item data...";
|
||||
|
||||
std::string error_string;
|
||||
|
@ -227,9 +289,6 @@ std::map<RsPeerId,PeerInfo>::iterator FriendServer::handleIncomingClientData(con
|
|||
mPgpHandler->syncDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
// All good.
|
||||
|
||||
// Store/update the peer info
|
||||
|
||||
auto& pi(mCurrentClientPeers[shortInviteDetails.id]);
|
||||
|
@ -238,12 +297,18 @@ std::map<RsPeerId,PeerInfo>::iterator FriendServer::handleIncomingClientData(con
|
|||
pi.last_connection_TS = time(nullptr);
|
||||
pi.pgp_fingerprint = shortInviteDetails.fpr;
|
||||
|
||||
while(pi.last_nonce == 0) // reuse the same identifier (so it's not really a nonce, but it's kept secret whatsoever).
|
||||
pi.last_nonce = RsRandom::random_u64();
|
||||
while(pi.last_identifier == 0) // reuse the same identifier (so it's not really a nonce, but it's kept secret whatsoever).
|
||||
pi.last_identifier = RsRandom::random_u64();
|
||||
|
||||
return mCurrentClientPeers.find(shortInviteDetails.id);
|
||||
pid = shortInviteDetails.id;
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
RsErr() << "Exception while adding client data: " << e.what() ;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item)
|
||||
{
|
||||
|
@ -257,14 +322,14 @@ void FriendServer::handleClientRemove(const RsFriendServerClientRemoveItem *item
|
|||
return;
|
||||
}
|
||||
|
||||
if(it->second.last_nonce != item->nonce)
|
||||
if(it->second.last_identifier != item->unique_identifier)
|
||||
{
|
||||
RsErr() << " ERROR: Client supplied a nonce " << std::hex << item->nonce << std::dec << " that is not correct (expected "
|
||||
<< std::hex << it->second.last_nonce << std::dec << ")";
|
||||
RsErr() << " ERROR: Client supplied a nonce " << std::hex << item->unique_identifier << std::dec << " that is not correct (expected "
|
||||
<< std::hex << it->second.last_identifier << std::dec << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
RsDbg() << " Nonce is correct: " << std::hex << item->nonce << std::dec << ". Removing peer " << item->peer_id ;
|
||||
RsDbg() << " Nonce is correct: " << std::hex << item->unique_identifier << std::dec << ". Removing peer " << item->peer_id ;
|
||||
|
||||
removePeer(item->peer_id);
|
||||
}
|
||||
|
@ -283,7 +348,7 @@ void FriendServer::removePeer(const RsPeerId& peer_id)
|
|||
for(auto pit(it.second.closest_peers.begin());pit!=it.second.closest_peers.end();)
|
||||
if(pit->second == peer_id)
|
||||
{
|
||||
RsDbg() << " Removing from n-closest peers of peer " << pit->first ;
|
||||
RsDbg() << " Removing from n-closest peers of peer " << it.first ;
|
||||
|
||||
auto tmp(pit);
|
||||
++tmp;
|
||||
|
@ -293,27 +358,26 @@ void FriendServer::removePeer(const RsPeerId& peer_id)
|
|||
else
|
||||
++pit;
|
||||
|
||||
// Also remove that peer from peers that have accepted each peer
|
||||
// Also remove that peer from friendship levels of that particular peer.
|
||||
|
||||
for(auto fit(it.second.have_added_this_peer.begin());fit!=it.second.have_added_this_peer.end();)
|
||||
if(fit->second == peer_id)
|
||||
auto fit = it.second.friendship_levels.find(peer_id);
|
||||
|
||||
if(fit != it.second.friendship_levels.end())
|
||||
{
|
||||
RsDbg() << " Removing from have_added_as_friend peers of peer " << fit->first ;
|
||||
|
||||
auto tmp(fit);
|
||||
++tmp;
|
||||
it.second.closest_peers.erase(fit);
|
||||
fit=tmp;
|
||||
RsDbg() << " Removing from have_added_as_friend peers of peer " << it.first ;
|
||||
it.second.friendship_levels.erase(fit);
|
||||
}
|
||||
else
|
||||
++fit;
|
||||
}
|
||||
}
|
||||
|
||||
PeerInfo::PeerDistance FriendServer::computePeerDistance(const RsPgpFingerprint& p1,const RsPgpFingerprint& p2)
|
||||
{
|
||||
std::cerr << "Computing peer distance: p1=" << p1 << " p2=" << p2 << " p1^p2=" << (p1^p2) << " distance=" << ((p1^p2)^mRandomPeerBias) << std::endl;
|
||||
return (p1 ^ p2)^mRandomPeerBias;
|
||||
auto res = (p1 ^ p2)^mRandomPeerBias;
|
||||
auto res2 = RsDirUtil::sha1sum(res.toByteArray(),res.SIZE_IN_BYTES); // sha1sum prevents reverse finding the random bias
|
||||
|
||||
std::cerr << "Computing peer distance: p1=" << p1 << " p2=" << p2 << " p1^p2=" << (p1^p2) << " distance=" << res2 << std::endl;
|
||||
|
||||
return res2;
|
||||
}
|
||||
FriendServer::FriendServer(const std::string& base_dir,const std::string& listening_address,uint16_t listening_port)
|
||||
: mListeningAddress(listening_address),mListeningPort(listening_port)
|
||||
|
@ -349,8 +413,6 @@ void FriendServer::run()
|
|||
void FriendServer::autoWash()
|
||||
{
|
||||
rstime_t now = time(nullptr);
|
||||
RsDbg() << "autoWash..." ;
|
||||
|
||||
std::list<RsPeerId> to_remove;
|
||||
|
||||
for(std::map<RsPeerId,PeerInfo>::iterator it(mCurrentClientPeers.begin());it!=mCurrentClientPeers.end();++it)
|
||||
|
@ -362,29 +424,116 @@ void FriendServer::autoWash()
|
|||
|
||||
for(auto peer_id:to_remove)
|
||||
removePeer(peer_id);
|
||||
|
||||
RsDbg() << "done." ;
|
||||
}
|
||||
|
||||
void FriendServer::updateClosestPeers(const RsPeerId& pid,const RsPgpFingerprint& fpr)
|
||||
void FriendServer::updateClosestPeers(const RsPeerId& pid,const RsPgpFingerprint& fpr,const std::map<RsPeerId,RsFriendServer::PeerFriendshipLevel>& friended_peers)
|
||||
{
|
||||
auto find_multi = [](PeerInfo::PeerDistance dist,std::map< std::pair<RsFriendServer::PeerFriendshipLevel,PeerInfo::PeerDistance>,RsPeerId >& mp)
|
||||
-> std::map< std::pair<RsFriendServer::PeerFriendshipLevel,PeerInfo::PeerDistance>,RsPeerId >::iterator
|
||||
{
|
||||
auto it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::UNKNOWN,dist)) ;
|
||||
|
||||
if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::NO_KEY ,dist));
|
||||
if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::HAS_KEY ,dist));
|
||||
if(it == mp.end()) it = mp.find(std::make_pair(RsFriendServer::PeerFriendshipLevel::HAS_ACCEPTED_KEY,dist));
|
||||
|
||||
return it;
|
||||
};
|
||||
auto remove_from_map = [find_multi](PeerInfo::PeerDistance dist,
|
||||
std::map< std::pair<RsFriendServer::PeerFriendshipLevel,
|
||||
PeerInfo::PeerDistance>,RsPeerId>& mp) -> bool
|
||||
{
|
||||
auto mpit = find_multi(dist,mp);
|
||||
|
||||
if(mpit != mp.end())
|
||||
{
|
||||
mp.erase(mpit);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
auto& pit(mCurrentClientPeers[pid]);
|
||||
|
||||
for(auto& it:mCurrentClientPeers)
|
||||
if(it.first != pid)
|
||||
{
|
||||
// 1 - for all existing peers, update the level at which the given peer has added the peer as friend.
|
||||
|
||||
auto peer_iterator = friended_peers.find(it.first);
|
||||
auto peer_friendship_level = (peer_iterator==friended_peers.end())? (RsFriendServer::PeerFriendshipLevel::UNKNOWN):(peer_iterator->second);
|
||||
|
||||
PeerInfo::PeerDistance d = computePeerDistance(fpr,it.second.pgp_fingerprint);
|
||||
|
||||
it.second.closest_peers.insert(std::make_pair(d,pid));
|
||||
// Remove the peer from the map. This is costly. I need to find something better. If the peer is already
|
||||
// in the list, it has a map key with the same distance.
|
||||
|
||||
if(it.second.closest_peers.size() > MAXIMUM_PEERS_TO_REQUEST)
|
||||
remove_from_map(d,it.second.closest_peers);
|
||||
|
||||
it.second.closest_peers[std::make_pair(peer_friendship_level,d)] = pid;
|
||||
|
||||
while(it.second.closest_peers.size() > MAXIMUM_PEERS_TO_REQUEST)
|
||||
it.second.closest_peers.erase(std::prev(it.second.closest_peers.end()));
|
||||
}
|
||||
|
||||
// 2 - for the current peer, update the list of closest peers
|
||||
|
||||
auto pit2 = it.second.friendship_levels.find(pid);
|
||||
peer_friendship_level = (pit2==it.second.friendship_levels.end())? (RsFriendServer::PeerFriendshipLevel::UNKNOWN):(pit2->second);
|
||||
|
||||
remove_from_map(d,pit.closest_peers);
|
||||
|
||||
pit.closest_peers[std::make_pair(peer_friendship_level,d)] = it.first;
|
||||
|
||||
while(pit.closest_peers.size() > MAXIMUM_PEERS_TO_REQUEST)
|
||||
pit.closest_peers.erase(std::prev(pit.closest_peers.end()));
|
||||
}
|
||||
|
||||
void FriendServer::debugPrint()
|
||||
// Also update the friendship levels for the current peer, of all friends from the list.
|
||||
|
||||
for(auto it:friended_peers)
|
||||
pit.friendship_levels[it.first] = it.second;
|
||||
}
|
||||
|
||||
Sha1CheckSum FriendServer::computeDataHash()
|
||||
{
|
||||
librs::crypto::HashStream s(librs::crypto::HashStream::SHA1);
|
||||
|
||||
for(auto p(mCurrentClientPeers.begin());p!=mCurrentClientPeers.end();++p)
|
||||
{
|
||||
s << p->first;
|
||||
|
||||
const auto& inf(p->second);
|
||||
|
||||
s << inf.pgp_fingerprint;
|
||||
s << inf.short_certificate;
|
||||
s << (uint64_t)inf.last_connection_TS;
|
||||
s << inf.last_identifier;
|
||||
|
||||
for(auto d(inf.closest_peers.begin());d!=inf.closest_peers.end();++d)
|
||||
{
|
||||
s << static_cast<uint32_t>(d->first.first) ;
|
||||
s << d->first.second ;
|
||||
s << d->second;
|
||||
}
|
||||
for(auto d:inf.friendship_levels)
|
||||
{
|
||||
s << d.first ;
|
||||
s << static_cast<uint32_t>(d.second);
|
||||
}
|
||||
}
|
||||
return s.hash();
|
||||
}
|
||||
void FriendServer::debugPrint(bool force)
|
||||
{
|
||||
auto h = computeDataHash();
|
||||
|
||||
if((h != mCurrentDataHash) || force)
|
||||
{
|
||||
RsDbg() << "========== FriendServer statistics ============";
|
||||
RsDbg() << " Base directory: "<< mBaseDirectory;
|
||||
RsDbg() << " Random peer bias: "<< mRandomPeerBias;
|
||||
RsDbg() << " Current hash: "<< h;
|
||||
RsDbg() << " Network interface: ";
|
||||
RsDbg() << " Max peers in n-closest list: " << MAXIMUM_PEERS_TO_REQUEST;
|
||||
RsDbg() << " Current active peers: " << mCurrentClientPeers.size() ;
|
||||
|
@ -393,20 +542,18 @@ void FriendServer::debugPrint()
|
|||
|
||||
for(const auto& it:mCurrentClientPeers)
|
||||
{
|
||||
RsDbg() << " " << it.first << ": nonce=" << std::hex << it.second.last_nonce << std::dec << " fpr: " << it.second.pgp_fingerprint << ", last contact: " << now - it.second.last_connection_TS << " secs ago.";
|
||||
RsDbg() << " " << it.first << ": identifier=" << std::hex << it.second.last_identifier << std::dec << " fpr: " << it.second.pgp_fingerprint << ", last contact: " << now - it.second.last_connection_TS << " secs ago.";
|
||||
RsDbg() << " Closest peers:" ;
|
||||
|
||||
for(const auto& pit:it.second.closest_peers)
|
||||
RsDbg() << " " << pit.second << " distance=" << pit.first ;
|
||||
|
||||
RsDbg() << " Have added this peer:" ;
|
||||
|
||||
for(const auto& pit:it.second.have_added_this_peer)
|
||||
RsDbg() << " " << pit.second << " distance=" << pit.first ;
|
||||
for(auto pit:it.second.closest_peers)
|
||||
RsDbg() << " " << pit.second << " distance=" << pit.first.second << " Peer reciprocal status:" << static_cast<int>(pit.first.first);
|
||||
}
|
||||
|
||||
RsDbg() << "===============================================";
|
||||
|
||||
mCurrentDataHash = h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,23 +24,108 @@
|
|||
#include "util/rsthreads.h"
|
||||
#include "pqi/pqistreamer.h"
|
||||
#include "pgp/pgphandler.h"
|
||||
#include "retroshare/rsfriendserver.h"
|
||||
|
||||
#include "network.h"
|
||||
|
||||
class RsFriendServerClientRemoveItem;
|
||||
class RsFriendServerClientPublishItem;
|
||||
|
||||
// +================================================================+
|
||||
// | o---o o |
|
||||
// | \ / - Retroshare Friend Server - / \ |
|
||||
// | o o---o |
|
||||
// +================================================================+
|
||||
//
|
||||
// The friend server facilitates a group of RS Tor-nodes to make friends. It maintains a pool of
|
||||
// participants (RS nodes currently susbscribing to the friend server) and advertise them to each other
|
||||
// as possible friends. Its goal is to allow new RS users to quickly experiment with the software without
|
||||
// compromising their anonymity.
|
||||
//
|
||||
// Implementation
|
||||
// ==============
|
||||
//
|
||||
// The implementation is entirely client-based: clients make a request, and get a response. No connection is maintained
|
||||
// beyond this interaction. Consequently, the friend server returns a random ID to each client that the client can use to
|
||||
// e.g. signal its departure from the friend server and the release of its data.
|
||||
//
|
||||
// Both client and server use a binary interface linked to a proxy-connected socket to stream RS items, everything
|
||||
// happenning on top of Tor connections.
|
||||
//
|
||||
// Algorithms
|
||||
// ==========
|
||||
//
|
||||
// * Protocol
|
||||
//
|
||||
// Retroshare Client Server (Friend Server)
|
||||
//
|
||||
// ------------ Tor connection --------> no action
|
||||
// Server online MSG <-------------- Tor ACK ------------
|
||||
//
|
||||
//
|
||||
// Friend Req. loop ------------ Friend Request --------> Friend list calculation / update
|
||||
// <---------- Friend list + ID --------
|
||||
//
|
||||
//
|
||||
// FS disabled ------------ FS Close + ID ---------> Data cleaning, peer removal.
|
||||
//
|
||||
//
|
||||
// * Friend selection
|
||||
//
|
||||
// In order to reduce the ease to retrieve the list of all participants to a friend server, the
|
||||
// friend server always returns the same list of friends to a given peer. To do so, participants are sorted
|
||||
// for each peer, using a XOR distance such as:
|
||||
//
|
||||
// d(P1,P2) = P1 (XOR) P2 (XOR) R
|
||||
//
|
||||
// ...where R is a random bias.
|
||||
//
|
||||
// Since being in the n closest peers is not a reflexive relationship (P1 may be within the n closest peers
|
||||
// to P2 but P2 may not be in the n closest peers to P1), selected friends for peer A are picked from both
|
||||
// the closest peers of A, and the peers that received the RS certificate of A.
|
||||
//
|
||||
// Another important effect of the stability of retrieved friends is to maintain a network that is not
|
||||
// fully connected and stable over time, which corresponds to the mesh model of the RS network.
|
||||
//
|
||||
// * Peer friendship level
|
||||
//
|
||||
// For display purposes, the friend server also stores the "friendship level" for each pair of peers,
|
||||
// that means whether the peer has added the other peer as friend, or only reveived his key, etc.
|
||||
//
|
||||
// Peers send to the friend server the list of peers they already have, with their own friendship
|
||||
// level with that peer. The FS needs to send back a list of peers, with the friendship level to the current peer.
|
||||
// In the list of closest peers, the reverse friendship levels are stored: for a peer A the reverse friendship
|
||||
// level to peer B is whether B has added A as friend or not.In the list of friends for a peer, the forward FL
|
||||
// is stored. The forward FL of a peer A to a peer B is whether A has added B as friend or not.
|
||||
//
|
||||
// * Security
|
||||
//
|
||||
// Obviously the friend server knows who is possibly connected to whom. Since the connections to the
|
||||
// friend server are anonymous, this information is difficult to protect, although the implementation
|
||||
// currently makes it difficult to retrieve.
|
||||
//
|
||||
// The friend server is only available to Tor nodes, since it allows RS nodes to connect to random peers.
|
||||
// This allows trying the software without compromizing one's privacy.
|
||||
|
||||
struct PeerInfo
|
||||
{
|
||||
typedef RsPgpFingerprint PeerDistance;
|
||||
typedef Sha1CheckSum PeerDistance;
|
||||
|
||||
RsPgpFingerprint pgp_fingerprint;
|
||||
std::string short_certificate;
|
||||
rstime_t last_connection_TS;
|
||||
uint64_t last_nonce;
|
||||
uint64_t last_identifier;
|
||||
|
||||
std::map<PeerDistance,RsPeerId> closest_peers;
|
||||
std::map<PeerDistance,RsPeerId> have_added_this_peer;
|
||||
// The following map contains the list of closest peers. The sorting is based
|
||||
// on a combination of the peer XOR distance and the friendship level, so that
|
||||
// peers which already have added a peer are considered first as potential receivers of his key.
|
||||
// The friendship level here is a reverse FL, e.g. whether each closest peer has added the current peer as friend.
|
||||
|
||||
std::map<std::pair<RsFriendServer::PeerFriendshipLevel,PeerDistance>,RsPeerId > closest_peers; // limited in size.
|
||||
|
||||
// Which peers have received the key for that particular peer, along with the direct friendship level: whether current peer has added each peer.
|
||||
|
||||
std::map<RsPeerId,RsFriendServer::PeerFriendshipLevel> friendship_levels; // unlimited in size, but no distance sorting.
|
||||
};
|
||||
|
||||
class FriendServer : public RsTickingThread
|
||||
|
@ -60,22 +145,25 @@ private:
|
|||
void handleClientPublish(const RsFriendServerClientPublishItem *item);
|
||||
|
||||
// Updates for each peer in the database, the list of closest peers w.r.t. some arbitrary distance.
|
||||
void updateClosestPeers(const RsPeerId& pid,const RsPgpFingerprint& fpr);
|
||||
void updateClosestPeers(const RsPeerId& pid, const RsPgpFingerprint& fpr, const std::map<RsPeerId, RsFriendServer::PeerFriendshipLevel> &friended_peers);
|
||||
|
||||
// removes a single peer from all lists.
|
||||
void removePeer(const RsPeerId& peer_id);
|
||||
|
||||
// Adds the incoming peer data to the list of current clients and returns the
|
||||
std::map<RsPeerId,PeerInfo>::iterator handleIncomingClientData(const std::string& pgp_public_key_b64,const std::string& short_invite_b64);
|
||||
bool handleIncomingClientData(const std::string& pgp_public_key_b64, const std::string& short_invite_b64, RsPeerId &pid);
|
||||
|
||||
// Computes the appropriate list of short invites to send to a given peer.
|
||||
std::map<std::string, bool> computeListOfFriendInvites(uint32_t nb_reqs_invites, const RsPeerId &pid, std::map<RsPeerId,RsPgpFingerprint>& friends);
|
||||
std::map<std::string,RsFriendServer::PeerFriendshipLevel> computeListOfFriendInvites(const RsPeerId &pid, uint32_t nb_reqs_invites,
|
||||
const std::map<RsPeerId,RsFriendServer::PeerFriendshipLevel>& already_known_peers,
|
||||
std::set<RsPeerId>& chosen_peers) const;
|
||||
|
||||
// Compute the distance between peers using the random bias (It's not really a distance though. I'm not sure about the triangular inequality).
|
||||
PeerInfo::PeerDistance computePeerDistance(const RsPgpFingerprint &p1, const RsPgpFingerprint &p2);
|
||||
|
||||
void autoWash();
|
||||
void debugPrint();
|
||||
void debugPrint(bool force);
|
||||
Sha1CheckSum computeDataHash();
|
||||
|
||||
// Local members
|
||||
|
||||
|
@ -88,4 +176,6 @@ private:
|
|||
std::map<RsPeerId, PeerInfo> mCurrentClientPeers;
|
||||
std::string mListeningAddress;
|
||||
uint16_t mListeningPort;
|
||||
|
||||
Sha1CheckSum mCurrentDataHash;
|
||||
};
|
||||
|
|
|
@ -27,6 +27,14 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#include "util/rsnet.h"
|
||||
#include "util/rsprint.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
@ -45,6 +53,9 @@ FsNetworkInterface::FsNetworkInterface(const std::string& listening_address,uint
|
|||
mClintListn = 0;
|
||||
mClintListn = socket(AF_INET, SOCK_STREAM, 0); // creating socket
|
||||
|
||||
int flags=1;
|
||||
setsockopt(mClintListn,SOL_SOCKET,TCP_NODELAY,(char*)&flags,sizeof(flags));
|
||||
|
||||
unix_fcntl_nonblock(mClintListn);
|
||||
|
||||
struct sockaddr_in ipOfServer;
|
||||
|
@ -102,15 +113,19 @@ void FsNetworkInterface::threadTick()
|
|||
|
||||
std::list<RsPeerId> to_close;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mFsNiMtx);
|
||||
for(auto& it:mConnections)
|
||||
if(it.second.bio->isactive())
|
||||
{
|
||||
it.second.pqi_thread->tick();
|
||||
else
|
||||
|
||||
if(!it.second.bio->isactive() && !it.second.bio->moretoread(0))
|
||||
to_close.push_back(it.first);
|
||||
}
|
||||
|
||||
for(const auto& pid:to_close)
|
||||
locked_closeConnection(pid);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
|
@ -134,7 +149,9 @@ bool FsNetworkInterface::checkForNewConnections()
|
|||
|
||||
if(clintConnt < 0)
|
||||
{
|
||||
if(errno == EWOULDBLOCK)
|
||||
int err = rs_socket_error();
|
||||
|
||||
if(err == EWOULDBLOCK || err == EAGAIN)
|
||||
;//RsErr()<< "Incoming connection with nothing to read!" << std::endl;
|
||||
else
|
||||
RsErr()<< "Error when accepting connection." << std::endl;
|
||||
|
@ -145,16 +162,24 @@ bool FsNetworkInterface::checkForNewConnections()
|
|||
|
||||
// Make the socket non blocking so that we can read from it and return if nothing comes
|
||||
|
||||
int flags=1;
|
||||
setsockopt(clintConnt,SOL_SOCKET,TCP_NODELAY,(char*)&flags,sizeof(flags));
|
||||
|
||||
unix_fcntl_nonblock(clintConnt);
|
||||
|
||||
// Create connection info
|
||||
|
||||
RsDbg() << " Creating connection data." ;
|
||||
|
||||
ConnectionData c;
|
||||
c.socket = clintConnt;
|
||||
c.client_address = addr;
|
||||
|
||||
RsPeerId pid = makePeerId(clintConnt);
|
||||
|
||||
RsDbg() << " socket: " << clintConnt;
|
||||
RsDbg() << " client address: " << sockaddr_storage_tostring(*(sockaddr_storage*)&addr);
|
||||
RsDbg() << " peer id: " << pid ;
|
||||
|
||||
// Setup a pqistreamer to deserialize whatever comes from this connection
|
||||
|
||||
RsSerialiser *rss = new RsSerialiser ;
|
||||
|
@ -167,11 +192,14 @@ bool FsNetworkInterface::checkForNewConnections()
|
|||
c.pqi_thread = pqi;
|
||||
c.bio = bio;
|
||||
|
||||
pqi->start();
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mFsNiMtx);
|
||||
mConnections[pid] = c;
|
||||
|
||||
pqi->start();
|
||||
}
|
||||
|
||||
RsDbg() << " streamer has properly started." ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -179,6 +207,8 @@ bool FsNetworkInterface::RecvItem(RsItem *item)
|
|||
{
|
||||
RS_STACK_MUTEX(mFsNiMtx);
|
||||
|
||||
RsDbg() << "FsNetworkInterface: received item " << (void*)item;
|
||||
|
||||
auto it = mConnections.find(item->PeerId());
|
||||
|
||||
if(it == mConnections.end())
|
||||
|
@ -203,6 +233,7 @@ RsItem *FsNetworkInterface::GetItem()
|
|||
RsItem *item = it.second.incoming_items.front();
|
||||
it.second.incoming_items.pop_front();
|
||||
|
||||
RsDbg() << "FsNetworkInterface: returning item " << (void*)item << " to caller.";
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "retroshare/rstor.h"
|
||||
#include "retroshare/rsinit.h"
|
||||
#include "pqi/authgpg.h"
|
||||
|
||||
#include "friendserver.h"
|
||||
|
||||
|
@ -47,20 +48,32 @@ int main(int argc, char* argv[])
|
|||
//RsControl::earlyInitNotificationSystem();
|
||||
|
||||
std::string base_directory = "FSData";
|
||||
std::string tor_executable_path ;
|
||||
bool verbose = false;
|
||||
|
||||
argstream as(argc,argv);
|
||||
|
||||
as >> parameter( 'c',"base-dir", base_directory, "set base directory to store data files (keys, etc)", false )
|
||||
>> parameter( 't',"tor-executable", tor_executable_path, "set absolute path for tor executable", false )
|
||||
>> option( 'v',"verbose", verbose, "display additional debug information")
|
||||
>> help( 'h', "help", "Display this Help" );
|
||||
|
||||
as.defaultErrorHandling(true, true);
|
||||
|
||||
RsConfigOptions conf;
|
||||
conf.optBaseDir = base_directory;
|
||||
conf.main_executable_path = argv[0];
|
||||
|
||||
if(!tor_executable_path.empty())
|
||||
RsTor::setTorExecutablePath(tor_executable_path);
|
||||
|
||||
RsTor::setVerbose(verbose);
|
||||
|
||||
RsInit::InitRsConfig();
|
||||
RsInit::InitRetroShare(conf);
|
||||
|
||||
AuthPGP::exit(); // This allows to release the keyring created by libretroshare, since it's not useful, as TorManager has its own.
|
||||
|
||||
// Create the base directory if needed
|
||||
|
||||
if(!RsDirUtil::checkCreateDirectory(base_directory))
|
||||
|
@ -68,6 +81,19 @@ int main(int argc, char* argv[])
|
|||
RsErr() << "Cannot create base directory \"" << base_directory << "\". Check permissions, paths, etc." ;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check the existance of the Tor executable path
|
||||
|
||||
auto tor_path = RsTor::torExecutablePath();
|
||||
|
||||
if (!RsDirUtil::fileExists(tor_path))
|
||||
{
|
||||
RsErr() << "Tor executable \"" << tor_path << "\" not found. Try supplying the correct full path for a tor executable with the -t option.";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
RsDbg() << "Using Tor executable: \"" << tor_path << "\"";
|
||||
|
||||
// Create/start TorManager
|
||||
|
||||
RsTor::setTorDataDirectory(RsDirUtil::makePath(base_directory,"tor"));
|
||||
|
@ -89,22 +115,22 @@ int main(int argc, char* argv[])
|
|||
|
||||
RsTor::getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,target_port) ;
|
||||
|
||||
RsDbg() << "Tor properly started: " ;
|
||||
RsDbg() << " Hidden service address: " << onion_address << ":" << service_port;
|
||||
RsDbg() << " Target address : " << service_target_address << ":" << target_port;
|
||||
RsInfo() << "Tor properly started: " ;
|
||||
RsInfo() << " Hidden service address: " << onion_address << ":" << service_port;
|
||||
RsInfo() << " Target address : " << service_target_address << ":" << target_port;
|
||||
|
||||
// Now start the real thing.
|
||||
|
||||
FriendServer fs(base_directory,service_target_address,target_port);
|
||||
fs.start();
|
||||
|
||||
RsDbg() << "";
|
||||
RsDbg() << "================== Retroshare Friend Server has properly started =====================" ;
|
||||
RsDbg() << "= =";
|
||||
RsDbg() << "= Address:Port " << onion_address << ":" << service_port << ((service_port<10000)?" ":"") << " =";
|
||||
RsDbg() << "= =";
|
||||
RsDbg() << "======================================================================================" ;
|
||||
RsDbg() << "";
|
||||
RsInfo() << "";
|
||||
RsInfo() << "================== Retroshare Friend Server has properly started =====================" ;
|
||||
RsInfo() << "= =";
|
||||
RsInfo() << "= Address:Port " << onion_address << ":" << service_port << ((service_port<10000)?" ":"") << " =";
|
||||
RsInfo() << "= =";
|
||||
RsInfo() << "======================================================================================" ;
|
||||
RsInfo() << "";
|
||||
|
||||
while(fs.isRunning())
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
|
|
|
@ -29,8 +29,7 @@ SOURCES += retroshare-friendserver.cc \
|
|||
network.cc
|
||||
|
||||
HEADERS += friendserver.h \
|
||||
network.h \
|
||||
fsitem.h
|
||||
network.h
|
||||
|
||||
################################# Linux ##########################################
|
||||
|
||||
|
@ -44,6 +43,7 @@ unix {
|
|||
win32-g++|win32-clang-g++ {
|
||||
dLib = ws2_32 iphlpapi crypt32
|
||||
LIBS *= $$linkDynamicLibs(dLib)
|
||||
CONFIG += console
|
||||
}
|
||||
|
||||
################################### COMMON stuff ##################################
|
||||
|
|
492
retroshare-gui/CMakeLists.txt
Normal file
492
retroshare-gui/CMakeLists.txt
Normal file
|
@ -0,0 +1,492 @@
|
|||
################################################################################
|
||||
# retroshare-gui/CMakeLists.txt #
|
||||
# Copyright (C) 2022, Retroshare team <retroshare.team@gmailcom> #
|
||||
# #
|
||||
# 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/>. #
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required (VERSION 3.18.0)
|
||||
project(retroshare-gui VERSION 0.6.6 LANGUAGES CXX)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
set(
|
||||
RS_BIN_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/bin"
|
||||
CACHE PATH
|
||||
"Path where to install retroshare-service compiled binary" )
|
||||
|
||||
option(
|
||||
RS_DEVELOPMENT_BUILD
|
||||
"Disable optimization to speed up build, enable verbose build log. \
|
||||
just for development purposes, not suitable for library usage"
|
||||
ON )
|
||||
|
||||
option(
|
||||
RS_JSON_API
|
||||
"Use restbed to expose libretroshare as JSON API via HTTP"
|
||||
OFF )
|
||||
|
||||
option(
|
||||
RS_SERVICE_DESKTOP
|
||||
"Install icons and shortcuts for desktop environements"
|
||||
OFF )
|
||||
|
||||
option(
|
||||
RS_SERVICE_TERMINAL_LOGIN
|
||||
"Enable RetroShare login via terminal"
|
||||
ON )
|
||||
|
||||
option( RS_GXSGUI "Enable GXS services in GUI" ON )
|
||||
option( RS_GXSCHANNELS "Enable GXS channels in GUI" ON )
|
||||
option( RS_GXSFORUMS "Enable GXS forums in GUI" ON )
|
||||
option( RS_GXSPOSTED "Enable GXS posted in GUI" ON )
|
||||
option( RS_GXSCIRCLES "Enable GXS circles in GUI" ON )
|
||||
|
||||
cmake_dependent_option(
|
||||
RS_SERVICE_TERMINAL_WEBUI_PASSWORD
|
||||
"Enable settin Web UI password via terminal in retroshare-service"
|
||||
OFF
|
||||
"RS_WEBUI"
|
||||
ON )
|
||||
|
||||
cmake_dependent_option(
|
||||
RS_WEBUI
|
||||
"Install RetroShare Web UI"
|
||||
OFF
|
||||
"RS_JSON_API"
|
||||
ON )
|
||||
|
||||
################################ QT FILES #######################################
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package( Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package( Qt5 COMPONENTS Widgets REQUIRED)
|
||||
find_package( Qt5 COMPONENTS Xml REQUIRED)
|
||||
find_package( Qt5 COMPONENTS Network REQUIRED)
|
||||
find_package( Qt5 COMPONENTS Multimedia REQUIRED)
|
||||
find_package( Qt5 COMPONENTS PrintSupport REQUIRED)
|
||||
|
||||
list( APPEND RS_LINK_LIBRARIES Qt5::Multimedia Qt5::Widgets Qt5::Xml Qt5::Network Qt5::PrintSupport)
|
||||
|
||||
################################################################################
|
||||
|
||||
set(FETCHCONTENT_QUIET OFF)
|
||||
include(FetchContent)
|
||||
|
||||
find_package(Git REQUIRED)
|
||||
|
||||
################################################################################
|
||||
|
||||
if(RS_DEVELOPMENT_BUILD)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
endif(RS_DEVELOPMENT_BUILD)
|
||||
|
||||
################################################################################
|
||||
|
||||
include(src/CMakeLists.txt)
|
||||
|
||||
qt5_wrap_ui(RS_UI_HEADERS ${RS_GUI_FORMS})
|
||||
|
||||
add_executable(${PROJECT_NAME} ${RS_GUI_SOURCES} ${RS_UI_HEADERS} ${RS_GUI_QTRESOURCES})
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION ${RS_BIN_INSTALL_DIR})
|
||||
|
||||
include_directories( ${CMAKE_BINARY_DIR} )
|
||||
|
||||
################################################################################
|
||||
|
||||
if(RS_DEVELOPMENT_BUILD)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE "-O0")
|
||||
endif(RS_DEVELOPMENT_BUILD)
|
||||
|
||||
################################################################################
|
||||
|
||||
set(LIBRETROSHARE_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libretroshare/")
|
||||
if(EXISTS "${LIBRETROSHARE_DEVEL_DIR}/.git" )
|
||||
message(
|
||||
STATUS
|
||||
"libretroshare submodule found at ${LIBRETROSHARE_DEVEL_DIR} using it" )
|
||||
add_subdirectory(
|
||||
"${LIBRETROSHARE_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/libretroshare" )
|
||||
else()
|
||||
FetchContent_Declare(
|
||||
libretroshare
|
||||
GIT_REPOSITORY "https://gitlab.com/RetroShare/libretroshare.git"
|
||||
GIT_TAG "origin/master"
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
TIMEOUT 10
|
||||
)
|
||||
FetchContent_MakeAvailable(libretroshare)
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBRETROSHARE_DEVEL_DIR}/src/)
|
||||
|
||||
################################################################################
|
||||
|
||||
if(RS_SERVICE_DESKTOP)
|
||||
if(UNIX AND NOT APPLE)
|
||||
install(
|
||||
FILES data/retroshare.svg
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/ )
|
||||
|
||||
install(
|
||||
FILES data/retroshare.xpm
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps/ )
|
||||
|
||||
install(
|
||||
FILES data/24x24/apps/retroshare.png
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/24x24/apps/retroshare.png )
|
||||
|
||||
install(
|
||||
FILES data/48x48/apps/retroshare.png
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/retroshare.png )
|
||||
|
||||
install(
|
||||
FILES data/64x64/apps/retroshare.png
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps/retroshare.png )
|
||||
|
||||
install(
|
||||
FILES data/128x128/apps/retroshare.png
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps/retroshare.png )
|
||||
|
||||
install(
|
||||
FILES data/retroshare.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/data/retroshare.desktop )
|
||||
|
||||
install(
|
||||
FILES gui/qss/chat/Bubble gui/qss/chat/Bubble_Compact
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/data/stylesheets/ )
|
||||
|
||||
install(
|
||||
FILES src/sounds/ src/qss/
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/ )
|
||||
endif(UNIX AND NOT APPLE)
|
||||
endif(RS_SERVICE_DESKTOP)
|
||||
|
||||
################################################################################
|
||||
|
||||
if(RS_JSON_API)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC RS_JSONAPI)
|
||||
endif(RS_JSON_API)
|
||||
|
||||
################################# CMark ########################################
|
||||
|
||||
if(RS_GUI_CMARK)
|
||||
set(CMARK_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../supportlibs/cmark/")
|
||||
if(EXISTS "${LIBRETROSHARE_DEVEL_DIR}/.git" )
|
||||
message( STATUS "cmark submodule found at ${LIBRETROSHARE_DEVEL_DIR} using it" )
|
||||
add_subdirectory( "${LIBRETROSHARE_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/cmark" )
|
||||
else()
|
||||
FetchContent_Declare(
|
||||
cmark
|
||||
GIT_REPOSITORY "https://github.com/commonmark/cmark.git"
|
||||
GIT_TAG "origin/master"
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
TIMEOUT 10
|
||||
)
|
||||
FetchContent_MakeAvailable(cmark)
|
||||
endif()
|
||||
endif(RS_GUI_CMARK)
|
||||
|
||||
################################# LibSam v3 ####################################
|
||||
|
||||
set(SAM3_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../supportlibs/libsam3/")
|
||||
if(EXISTS "${SAM3_DEVEL_DIR}/.git" )
|
||||
message( STATUS "libsam3 submodule found at ${SAM3_DEVEL_DIR} using it" )
|
||||
add_subdirectory( "${SAM3_DEVEL_DIR}" "${CMAKE_BINARY_DIR}/libsam3" )
|
||||
else()
|
||||
FetchContent_Declare(
|
||||
libsam3
|
||||
GIT_REPOSITORY "https://github.com/i2p/libsam3.git"
|
||||
GIT_TAG "origin/master"
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
TIMEOUT 10
|
||||
)
|
||||
FetchContent_MakeAvailable(libsam3)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# TODO #
|
||||
################################################################################
|
||||
|
||||
# # Auto detect installed version of cmark
|
||||
# rs_gui_cmark {
|
||||
# DEFINES *= USE_CMARK
|
||||
# no_rs_cross_compiling {
|
||||
# message("Using compiled cmark")
|
||||
# CMARK_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/cmark)
|
||||
# CMARK_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/cmark/build)
|
||||
# INCLUDEPATH *= $$clean_path($${CMARK_SRC_PATH}/src/)
|
||||
# DEPENDPATH *= $$clean_path($${CMARK_SRC_PATH}/src/)
|
||||
# QMAKE_LIBDIR *= $$clean_path($${CMARK_BUILD_PATH}/)
|
||||
# # Using sLibs would fail as libcmark.a is generated at compile-time
|
||||
# LIBS *= -L$$clean_path($${CMARK_BUILD_PATH}/src/) -lcmark
|
||||
#
|
||||
# DUMMYCMARKINPUT = FORCE
|
||||
# CMAKE_GENERATOR_OVERRIDE=""
|
||||
# win32-g++|win32-clang-g++:CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\""
|
||||
# gencmarklib.name = Generating libcmark.
|
||||
# gencmarklib.input = DUMMYCMARKINPUT
|
||||
# gencmarklib.output = $$clean_path($${CMARK_BUILD_PATH}/src/libcmark.a)
|
||||
# gencmarklib.CONFIG += target_predeps combine
|
||||
# gencmarklib.variable_out = PRE_TARGETDEPS
|
||||
# gencmarklib.commands = \
|
||||
# cd $${RS_SRC_PATH} && ( \
|
||||
# git submodule update --init supportlibs/cmark ; \
|
||||
# cd $${CMARK_SRC_PATH} ; \
|
||||
# true ) && \
|
||||
# mkdir -p $${CMARK_BUILD_PATH} && cd $${CMARK_BUILD_PATH} && \
|
||||
# cmake \
|
||||
# -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \
|
||||
# \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \
|
||||
# $${CMAKE_GENERATOR_OVERRIDE} \
|
||||
# -DCMAKE_INSTALL_PREFIX=. \
|
||||
# -B. \
|
||||
# -H$$shell_path($${CMARK_SRC_PATH}) && \
|
||||
# $(MAKE)
|
||||
# QMAKE_EXTRA_COMPILERS += gencmarklib
|
||||
# } else {
|
||||
# message("Using systems cmark")
|
||||
# sLibs *= libcmark
|
||||
# }
|
||||
# }
|
||||
|
||||
################################# Linux ##########################################
|
||||
# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib
|
||||
|
||||
if(UNIX)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(X11 REQUIRED x11)
|
||||
pkg_check_modules(XSCRNSAVER REQUIRED xscrnsaver)
|
||||
|
||||
list( APPEND RS_LINK_LIBRARIES ${X11_LIBRARIES} )
|
||||
list( APPEND RS_LINK_LIBRARIES ${XSCRNSAVER_LIBRARIES} )
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${X11_INCLUDE_DIRS})
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${X11_CFLAGS_OTHER})
|
||||
|
||||
target_include_directories(retroshare-gui PRIVATE ${XSCRNSAVER_INCLUDE_DIRS})
|
||||
target_compile_options(retroshare-gui PRIVATE ${XSCRNSAVER_CFLAGS_OTHER})
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE HAVE_XSS)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE _FILE_OFFSET_BITS=64)
|
||||
target_link_options(${PROJECT_NAME} PRIVATE LINKER:-rdynamic)
|
||||
endif(UNIX)
|
||||
|
||||
if(RS_SANITIZE)
|
||||
list( APPEND RS_LINK_LIBRARIES asan )
|
||||
list( APPEND RS_LINK_LIBRARIES ubsan )
|
||||
endif(RS_SANITIZE)
|
||||
|
||||
# #################### Cross compilation for windows under Linux ###################
|
||||
#
|
||||
# win32-x-g++ {
|
||||
# OBJECTS_DIR = temp/win32-x-g++/obj
|
||||
#
|
||||
# LIBS += ../../../../lib/win32-x-g++-v0.5/libssl.a
|
||||
# LIBS += ../../../../lib/win32-x-g++-v0.5/libcrypto.a
|
||||
# LIBS += ../../../../lib/win32-x-g++-v0.5/libgpgme.dll.a
|
||||
# LIBS += ../../../../lib/win32-x-g++-v0.5/libminiupnpc.a
|
||||
# LIBS += ../../../../lib/win32-x-g++-v0.5/libz.a
|
||||
# LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2
|
||||
# LIBS += -lQtUiTools
|
||||
# LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32
|
||||
# LIBS += -lole32 -lwinmm
|
||||
#
|
||||
# DEFINES *= WINDOWS_SYS WIN32 WIN32_CROSS_UBUNTU
|
||||
#
|
||||
# INCLUDEPATH += ../../../../gpgme-1.1.8/src/
|
||||
# INCLUDEPATH += ../../../../libgpg-error-1.7/src/
|
||||
#
|
||||
# RC_FILE = gui/images/retroshare_win.rc
|
||||
# }
|
||||
#
|
||||
# #################################### Windows #####################################
|
||||
#
|
||||
# win32-g++|win32-clang-g++ {
|
||||
# CONFIG(debug, debug|release) {
|
||||
# # show console output
|
||||
# CONFIG += console
|
||||
# } else {
|
||||
# CONFIG -= console
|
||||
# }
|
||||
#
|
||||
# CONFIG(debug, debug|release) {
|
||||
# } else {
|
||||
# # Tell linker to use ASLR protection
|
||||
# QMAKE_LFLAGS += -Wl,-dynamicbase
|
||||
# # Tell linker to use DEP protection
|
||||
# QMAKE_LFLAGS += -Wl,-nxcompat
|
||||
# }
|
||||
#
|
||||
# # Fix linking error (ld.exe: Error: export ordinal too large) due to too
|
||||
# # many exported symbols.
|
||||
# !libretroshare_shared:QMAKE_LFLAGS+=-Wl,--exclude-libs,ALL
|
||||
#
|
||||
# # Switch off optimization for release version
|
||||
# QMAKE_CXXFLAGS_RELEASE -= -O2
|
||||
# QMAKE_CXXFLAGS_RELEASE += -O0
|
||||
# QMAKE_CFLAGS_RELEASE -= -O2
|
||||
# QMAKE_CFLAGS_RELEASE += -O0
|
||||
#
|
||||
# # Switch on optimization for debug version
|
||||
# #QMAKE_CXXFLAGS_DEBUG += -O2
|
||||
# #QMAKE_CFLAGS_DEBUG += -O2
|
||||
#
|
||||
# OBJECTS_DIR = temp/obj
|
||||
#
|
||||
# dLib = ws2_32 gdi32 uuid ole32 iphlpapi crypt32 winmm
|
||||
# LIBS *= $$linkDynamicLibs(dLib)
|
||||
#
|
||||
# RC_FILE = gui/images/retroshare_win.rc
|
||||
#
|
||||
# # export symbols for the plugins
|
||||
# LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a
|
||||
#
|
||||
# # create lib directory
|
||||
# isEmpty(QMAKE_SH) {
|
||||
# QMAKE_PRE_LINK = $(CHK_DIR_EXISTS) lib $(MKDIR) lib
|
||||
# } else {
|
||||
# QMAKE_PRE_LINK = $(CHK_DIR_EXISTS) lib || $(MKDIR) lib
|
||||
# }
|
||||
#
|
||||
# greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
# # Qt 5
|
||||
# RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src
|
||||
# } else {
|
||||
# # Qt 4
|
||||
# QMAKE_RC += --include-dir=$$_PRO_FILE_PWD_/../../libretroshare/src
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# ##################################### MacOS ######################################
|
||||
#
|
||||
# macx {
|
||||
# # ENABLE THIS OPTION FOR Univeral Binary BUILD.
|
||||
# #CONFIG += ppc x86
|
||||
# #QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4
|
||||
# QMAKE_INFO_PLIST = Info.plist
|
||||
# mac_icon.files = $$files($$PWD/rsMacIcon.icns)
|
||||
# mac_icon.path = Contents/Resources
|
||||
# QMAKE_BUNDLE_DATA += mac_icon
|
||||
# dplQSS.files = $$PWD/qss
|
||||
# dplQSS.path = Contents/Resources
|
||||
# QMAKE_BUNDLE_DATA += dplQSS
|
||||
# dplChatStyles.files = \
|
||||
# $$PWD/gui/qss/chat/Bubble \
|
||||
# $$PWD/gui/qss/chat/Bubble_Compact
|
||||
# dplChatStyles.path = Contents/Resources/stylesheets
|
||||
# QMAKE_BUNDLE_DATA += dplChatStyles
|
||||
# # mac_webui.files = $$files($$PWD/../../libresapi/src/webui)
|
||||
# # mac_webui.path = Contents/Resources
|
||||
# # QMAKE_BUNDLE_DATA += mac_webui
|
||||
#
|
||||
# OBJECTS_DIR = temp/obj
|
||||
#
|
||||
# CONFIG += version_detail_bash_script
|
||||
# LIBS += -lssl -lcrypto -lz
|
||||
# for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a}
|
||||
# LIBS += -framework CoreFoundation
|
||||
# LIBS += -framework Security
|
||||
# LIBS += -framework Carbon
|
||||
#
|
||||
# for(lib, LIB_DIR):LIBS += -L"$$lib"
|
||||
# for(bin, BIN_DIR):LIBS += -L"$$bin"
|
||||
#
|
||||
# DEPENDPATH += . $$INC_DIR
|
||||
# INCLUDEPATH += . $$INC_DIR
|
||||
#
|
||||
# #DEFINES *= MAC_IDLE # for idle feature
|
||||
# CONFIG -= uitools
|
||||
# }
|
||||
#
|
||||
# ##################################### FreeBSD ######################################
|
||||
#
|
||||
# freebsd-* {
|
||||
# INCLUDEPATH *= /usr/local/include/gpgme
|
||||
# LIBS *= -lssl
|
||||
# LIBS *= -lgpgme
|
||||
# LIBS *= -lupnp
|
||||
# LIBS *= -lgnome-keyring
|
||||
#
|
||||
# LIBS += -lsqlite3
|
||||
# }
|
||||
#
|
||||
# ##################################### Haiku ######################################
|
||||
#
|
||||
# haiku-* {
|
||||
# PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
|
||||
# PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
|
||||
#
|
||||
# LIBS *= ../../libretroshare/src/lib/libretroshare.a
|
||||
# LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2 -lbsd
|
||||
# LIBS *= -lssl -lcrypto -lnetwork
|
||||
# LIBS *= -lgpgme
|
||||
# LIBS *= -lupnp
|
||||
# LIBS *= -lz
|
||||
# LIBS *= -lixml
|
||||
#
|
||||
# LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
|
||||
# LIBS += -lsqlite3
|
||||
# }
|
||||
#
|
||||
# ##################################### OpenBSD ######################################
|
||||
#
|
||||
# openbsd-* {
|
||||
# INCLUDEPATH *= /usr/local/include
|
||||
#
|
||||
# LIBS *= -lssl -lcrypto
|
||||
# LIBS *= -lgpgme
|
||||
# LIBS *= -lupnp
|
||||
# LIBS *= -lgnome-keyring
|
||||
# LIBS += -lsqlite3
|
||||
# LIBS *= -rdynamic
|
||||
# }
|
||||
#
|
||||
# ################################### COMMON stuff ##################################
|
||||
#
|
||||
# wikipoos {
|
||||
# PRE_TARGETDEPS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
|
||||
# LIBS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
|
||||
# LIBS *= -lglib-2.0
|
||||
# }
|
||||
|
||||
################################ GENERAL #######################################
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${RS_LINK_LIBRARIES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/)
|
||||
|
||||
set( CMAKE_CXX_FLAGS "-Wno-deprecated-declarations" )
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC RS_NO_WARN_DEPRECATED )
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE RS_RELEASE_VERSION )
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE TARGET=\"retroshare\")
|
||||
|
||||
if(RS_GXS_CIRCLES)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE RS_USE_CIRCLES )
|
||||
endif(RS_GXS_CIRCLES)
|
||||
|
||||
#add_dependencies(${PROJECT_NAME} libretroshare)
|
||||
|
1279
retroshare-gui/src/CMakeLists.txt
Normal file
1279
retroshare-gui/src/CMakeLists.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,17 +2,14 @@
|
|||
README for RetroShare
|
||||
=======================================================================================
|
||||
|
||||
RetroShare web site . . . . http://retroshare.net/index.html
|
||||
RetroShare web site . . . . https://retroshare.cc/
|
||||
Developer's blog . . . . . https://retroshareteam.wordpress.com
|
||||
Documentation . . . . . . . https://retroshare.readthedocs.io/en/latest/
|
||||
Support . . . . . . . . . . http://retroshare.net/support.html
|
||||
Forums . . . . . . . . . . http://retroshare.sourceforge.net/forum/
|
||||
Documentation . . . . . . . https://retrosharedocs.readthedocs.io/en/latest/
|
||||
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
|
||||
Relted projects/plugins . . https://github.com/RetroShare
|
||||
Related projects/plugins . .https://github.com/RetroShare
|
||||
|
||||
Contact: . . . . . . . . . retroshare@lunamutt.com ,defnax@users.sourceforge.net
|
||||
Contact: . . . . . . . . . retroshare.project@gmail.com
|
||||
|
||||
=========================================================================================
|
||||
Compiling RetroShare
|
||||
|
@ -22,9 +19,9 @@ Build Scripts are avaible on GIT:
|
|||
https://github.com/RetroShare/RetroShare/tree/master/build_scripts
|
||||
|
||||
You can find here instructions howto compile RetroShare:
|
||||
https://retroshare.readthedocs.io/en/latest/developer/compilation/
|
||||
https://retrosharedocs.readthedocs.io/en/latest/developer/compilation/
|
||||
|
||||
You can go on over to our forum or chat lobby when you have trouble with compiling:
|
||||
You can go on over to our forum or chat room when you have trouble with compiling:
|
||||
retroshare://forum?name=Developers%20Discussions&id=8fd22bd8f99754461e7ba1ca8a727995
|
||||
retroshare://chat_room?name=Retroshare%20Devel%20%28signed%29&id=L68DB0A1E09BDA3A5
|
||||
http://retroshare.sourceforge.net/forum/
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "AboutDialog.h"
|
||||
#include "HelpDialog.h"
|
||||
#include "qmake_info.h"
|
||||
#include "include/qmake_info.h"
|
||||
#include "rshare.h"
|
||||
|
||||
#ifdef RS_JSONAPI
|
||||
|
@ -142,7 +142,7 @@ void AboutWidget::updateTitle()
|
|||
{
|
||||
if (tWidget == NULL)
|
||||
{
|
||||
setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), Rshare::retroshareVersion(true)));
|
||||
setWindowTitle(QString("%1 %2").arg(tr("About RetroShare"), RsApplication::retroshareVersion(true)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ void AWidget::initImages()
|
|||
#ifdef RS_ONLYHIDDENNODE
|
||||
p.drawText(QPointF(10, 50), QString("%1 : %2 (With embedded Tor)").arg(tr("Retroshare version"), Rshare::retroshareVersion(true)));
|
||||
#else
|
||||
p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), Rshare::retroshareVersion(true)));
|
||||
p.drawText(QPointF(10, 50), QString("%1 : %2").arg(tr("Retroshare version"), RsApplication::retroshareVersion(true)));
|
||||
#endif
|
||||
|
||||
/* Draw Qt's version number */
|
||||
|
@ -936,7 +936,7 @@ void AboutWidget::on_copy_button_clicked()
|
|||
{
|
||||
QString verInfo;
|
||||
QString rsVerString = "RetroShare Version: ";
|
||||
rsVerString+=Rshare::retroshareVersion(true);
|
||||
rsVerString+=RsApplication::retroshareVersion(true);
|
||||
verInfo+=rsVerString;
|
||||
#ifdef RS_ONLYHIDDENNODE
|
||||
verInfo+=" " + tr("Only Hidden Node");
|
||||
|
|
|
@ -22,19 +22,20 @@
|
|||
#include "ChatLobbyWidget.h"
|
||||
|
||||
#include "notifyqt.h"
|
||||
#include "RetroShareLink.h"
|
||||
#include "chat/ChatLobbyDialog.h"
|
||||
#include "chat/ChatLobbyUserNotify.h"
|
||||
#include "chat/ChatTabWidget.h"
|
||||
#include "chat/CreateLobbyDialog.h"
|
||||
#include "common/FilesDefs.h"
|
||||
#include "common/RSTreeWidgetItem.h"
|
||||
#include "common/RSElidedItemDelegate.h"
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
#include "gui/Identity/IdEditDialog.h"
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
#include "gxs/GxsIdDetails.h"
|
||||
#include "Identity/IdEditDialog.h"
|
||||
#include "settings/rsharesettings.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "gui/common/FilesDefs.h"
|
||||
|
||||
#include "retroshare/rsmsgs.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
@ -142,28 +143,28 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags)
|
|||
QHeaderView_setSectionResizeModeColumn(header, COLUMN_TOPIC, QHeaderView::Interactive);
|
||||
|
||||
privateSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed chat rooms"));
|
||||
privateSubLobbyItem->setText(COLUMN_NAME, tr("Private Subscribed"));
|
||||
privateSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "1");
|
||||
// privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE));
|
||||
privateSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE);
|
||||
ui.lobbyTreeWidget->insertTopLevelItem(0, privateSubLobbyItem);
|
||||
|
||||
publicSubLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms"));
|
||||
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed"));
|
||||
publicSubLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "2");
|
||||
// publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
|
||||
publicSubLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC);
|
||||
ui.lobbyTreeWidget->insertTopLevelItem(1, publicSubLobbyItem);
|
||||
|
||||
privateLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
privateLobbyItem->setText(COLUMN_NAME, tr("Private chat rooms"));
|
||||
privateLobbyItem->setText(COLUMN_NAME, tr("Private"));
|
||||
privateLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "3");
|
||||
// privateLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE));
|
||||
privateLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE);
|
||||
ui.lobbyTreeWidget->insertTopLevelItem(2, privateLobbyItem);
|
||||
|
||||
publicLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms"));
|
||||
publicLobbyItem->setText(COLUMN_NAME, tr("Public"));
|
||||
publicLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "4");
|
||||
// publicLobbyItem->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
|
||||
publicLobbyItem->setData(COLUMN_DATA, ROLE_PRIVACYLEVEL, CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC);
|
||||
|
@ -206,28 +207,29 @@ ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WindowFlags flags)
|
|||
// load settings
|
||||
processSettings(true);
|
||||
|
||||
QString help_str = tr("\
|
||||
<h1><img width=\"%1\" src=\":/icons/help_64.png\"> Chat Rooms</h1> \
|
||||
<p>Chat rooms work pretty much like IRC. \
|
||||
They allow you to talk anonymously with tons of people without the need to make friends.</p> \
|
||||
<p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you \
|
||||
invite them with <img src=\":/icons/png/add.png\" width=%2/>). \
|
||||
Once you have been invited to a private room, you will be able to see it when your friends \
|
||||
are using it.</p> \
|
||||
<p>The list at left shows \
|
||||
chat lobbies your friends are participating in. You can either \
|
||||
<ul> \
|
||||
<li>Right click to create a new chat room</li> \
|
||||
<li>Double click a chat room to enter, chat, and show it to your friends</li> \
|
||||
</ul> \
|
||||
Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!\
|
||||
</p> \
|
||||
"
|
||||
).arg(QString::number(4*W), QString::number(2*W)) ;
|
||||
int hbH = misc::getFontSizeFactor("HelpButton").height();
|
||||
QString help_str = tr(
|
||||
"<h1><img width=\"%1\" src=\":/icons/help_64.png\"> Chat Rooms</h1>"
|
||||
"<p>Chat rooms work pretty much like IRC."
|
||||
" They allow you to talk anonymously with tons of people without the need to make friends.</p>"
|
||||
"<p>A chat room can be public (your friends see it) or private (your friends can't see it, unless you"
|
||||
" invite them with <img src=\":/icons/png/add.png\" width=%2/>)."
|
||||
" Once you have been invited to a private room, you will be able to see it when your friends"
|
||||
" are using it.</p>"
|
||||
"<p>The list at left shows"
|
||||
" chat lobbies your friends are participating in. You can either"
|
||||
" <ul>"
|
||||
" <li>Right click to create a new chat room</li>"
|
||||
" <li>Double click a chat room to enter, chat, and show it to your friends</li>"
|
||||
" </ul>"
|
||||
" Note: For the chat rooms to work properly, your computer needs be on time. So check your system clock!"
|
||||
"</p>"
|
||||
).arg(QString::number(2*hbH), QString::number(hbH)) ;
|
||||
|
||||
registerHelpButton(ui.helpButton,help_str,"ChatLobbyDialog") ;
|
||||
|
||||
ui.lobbyTreeWidget->setIconSize(QSize(H*1.5,H*1.5));
|
||||
int ltwH = misc::getFontSizeFactor("LobbyTreeWidget", 1.5).height();
|
||||
ui.lobbyTreeWidget->setIconSize(QSize(ltwH,ltwH));
|
||||
}
|
||||
|
||||
ChatLobbyWidget::~ChatLobbyWidget()
|
||||
|
@ -306,9 +308,6 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
|
|||
contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_UNSUBSCRIBE), tr("Leave this room"), this, SLOT(unsubscribeItem()));
|
||||
else
|
||||
{
|
||||
QTreeWidgetItem *item = ui.lobbyTreeWidget->currentItem();
|
||||
|
||||
//ChatLobbyId id = item->data(COLUMN_DATA, ROLE_ID).toULongLong();
|
||||
ChatLobbyFlags flags(item->data(COLUMN_DATA, ROLE_FLAGS).toUInt());
|
||||
|
||||
bool removed = false ;
|
||||
|
@ -373,7 +372,7 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
|
|||
|
||||
void ChatLobbyWidget::lobbyChanged()
|
||||
{
|
||||
updateDisplay();
|
||||
ChatLobbyWidget::updateDisplay();
|
||||
}
|
||||
|
||||
static void updateItem(QTreeWidget *treeWidget, QTreeWidgetItem *item, ChatLobbyId id, const std::string &name, const std::string &topic, int count, bool subscribed, bool autoSubscribe,ChatLobbyFlags lobby_flags)
|
||||
|
@ -607,7 +606,7 @@ void ChatLobbyWidget::updateDisplay()
|
|||
QTreeWidgetItem *itemLoop = lobby_other_item->child(childIndex);
|
||||
if (itemLoop->type() == TYPE_LOBBY && itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobby.lobby_id) {
|
||||
delete(lobby_other_item->takeChild(lobby_other_item->indexOfChild(itemLoop)));
|
||||
childCnt = lobby_other_item->childCount();
|
||||
//childCnt = lobby_other_item->childCount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -722,9 +721,9 @@ void ChatLobbyWidget::updateDisplay()
|
|||
}
|
||||
}
|
||||
publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0);
|
||||
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
|
||||
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
|
||||
privateSubLobbyItem->setHidden(privateSubLobbyItem->childCount()==0);
|
||||
publicLobbyItem->setText(COLUMN_NAME, tr("Public chat rooms")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")"));
|
||||
publicLobbyItem->setText(COLUMN_NAME, tr("Public")+ " (" + QString::number(publicLobbyItem->childCount())+QString(")"));
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::createChatLobby()
|
||||
|
|
|
@ -56,18 +56,18 @@ class ChatLobbyWidget : public RsAutoUpdatePage
|
|||
|
||||
public:
|
||||
/** Default constructor */
|
||||
ChatLobbyWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0);
|
||||
ChatLobbyWidget(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
|
||||
/** Default destructor */
|
||||
~ChatLobbyWidget();
|
||||
|
||||
virtual QIcon iconPixmap() const { return QIcon(IMAGE_CHATLOBBY) ; } //MainPage
|
||||
virtual QString pageName() const { return tr("Chats") ; } //MainPage
|
||||
virtual QString helpText() const { return ""; } //MainPage
|
||||
virtual QIcon iconPixmap() const override { return QIcon(IMAGE_CHATLOBBY) ; } //MainPage
|
||||
virtual QString pageName() const override { return tr("Chats") ; } //MainPage
|
||||
virtual QString helpText() const override { return ""; } //MainPage
|
||||
|
||||
virtual UserNotify *createUserNotify(QObject *parent) override; //MainPage
|
||||
|
||||
virtual void updateDisplay();
|
||||
virtual void updateDisplay() override; //RsAutoUpdatePage
|
||||
|
||||
void setCurrentChatPage(ChatLobbyDialog *) ; // used by ChatLobbyDialog to raise.
|
||||
void addChatPage(ChatLobbyDialog *) ;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "gui/Circles/CirclesDialog.h"
|
||||
#include "gui/Circles/CreateCircleDialog.h"
|
||||
#include "gui/common/UIStateHelper.h"
|
||||
#include "util/qtthreadsutils.h"
|
||||
|
||||
#include <retroshare/rsgxscircles.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
|
@ -72,9 +73,6 @@ CirclesDialog::CirclesDialog(QWidget *parent)
|
|||
|
||||
connect(ui.treeWidget_membership, SIGNAL(itemSelectionChanged()), this, SLOT(circle_selected()));
|
||||
|
||||
/* Setup TokenQueue */
|
||||
mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this);
|
||||
|
||||
/* Set header resize modes and initial section sizes */
|
||||
QHeaderView * membership_header = ui.treeWidget_membership->header () ;
|
||||
membership_header->resizeSection ( CIRCLEGROUP_CIRCLE_COL_GROUPNAME, 200 );
|
||||
|
@ -82,7 +80,6 @@ CirclesDialog::CirclesDialog(QWidget *parent)
|
|||
|
||||
CirclesDialog::~CirclesDialog()
|
||||
{
|
||||
delete mCircleQueue;
|
||||
}
|
||||
|
||||
void CirclesDialog::todo()
|
||||
|
@ -564,38 +561,36 @@ void CirclesDialog::requestGroupMeta()
|
|||
{
|
||||
mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, true);
|
||||
|
||||
std::cerr << "CirclesDialog::requestGroupMeta()";
|
||||
std::cerr << std::endl;
|
||||
RsThread::async([this]()
|
||||
{
|
||||
std::list<RsGroupMetaData> circles;
|
||||
|
||||
mCircleQueue->cancelActiveRequestTokens(CIRCLESDIALOG_GROUPMETA);
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_META;
|
||||
|
||||
uint32_t token;
|
||||
mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, CIRCLESDIALOG_GROUPMETA);
|
||||
if(!rsGxsCircles->getCirclesSummaries(circles))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " failed to get circles summaries " << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void CirclesDialog::loadGroupMeta(const uint32_t &token)
|
||||
RsQThreadUtils::postToObject( [this,circles]()
|
||||
{
|
||||
/* 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!
|
||||
*/
|
||||
|
||||
loadGroupMeta(circles);
|
||||
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
|
||||
void CirclesDialog::loadGroupMeta(const std::list<RsGroupMetaData>& groupInfo)
|
||||
{
|
||||
mStateHelper->setLoading(CIRCLESDIALOG_GROUPMETA, false);
|
||||
|
||||
std::cerr << "CirclesDialog::loadGroupMeta()";
|
||||
std::cerr << std::endl;
|
||||
|
||||
ui.treeWidget_membership->clear();
|
||||
|
||||
std::list<RsGroupMetaData> groupInfo;
|
||||
std::list<RsGroupMetaData>::iterator vit;
|
||||
|
||||
if (!rsGxsCircles->getGroupSummary(token,groupInfo))
|
||||
{
|
||||
std::cerr << "CirclesDialog::loadGroupMeta() Error getting GroupMeta";
|
||||
std::cerr << std::endl;
|
||||
mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, false);
|
||||
return;
|
||||
}
|
||||
|
||||
mStateHelper->setActive(CIRCLESDIALOG_GROUPMETA, true);
|
||||
|
||||
/* add the top level item */
|
||||
|
@ -615,7 +610,7 @@ void CirclesDialog::loadGroupMeta(const uint32_t &token)
|
|||
externalOtherCirclesItem->setText(0, tr("External Circles (Other)"));
|
||||
ui.treeWidget_membership->addTopLevelItem(externalOtherCirclesItem);
|
||||
|
||||
for(vit = groupInfo.begin(); vit != groupInfo.end(); ++vit)
|
||||
for(auto vit = groupInfo.begin(); vit != groupInfo.end(); ++vit)
|
||||
{
|
||||
/* Add Widget, and request Pages */
|
||||
std::cerr << "CirclesDialog::loadGroupMeta() GroupId: " << vit->mGroupId;
|
||||
|
@ -647,25 +642,3 @@ void CirclesDialog::loadGroupMeta(const uint32_t &token)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CirclesDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
{
|
||||
std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (queue == mCircleQueue)
|
||||
{
|
||||
/* now switch on req */
|
||||
switch(req.mUserType)
|
||||
{
|
||||
case CIRCLESDIALOG_GROUPMETA:
|
||||
loadGroupMeta(req.mToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "CirclesDialog::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,13 @@
|
|||
#define MRK_CIRCLE_DIALOG_H
|
||||
|
||||
#include "gui/gxs/RsGxsUpdateBroadcastPage.h"
|
||||
#include "util/TokenQueue.h"
|
||||
#include "ui_CirclesDialog.h"
|
||||
|
||||
#define IMAGE_CIRCLES ":/icons/png/circles.png"
|
||||
|
||||
class UIStateHelper;
|
||||
|
||||
class CirclesDialog : public MainPage, public TokenResponse
|
||||
class CirclesDialog : public MainPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -43,8 +42,6 @@ public:
|
|||
virtual QString pageName() const { return tr("Circles") ; } //MainPage
|
||||
virtual QString helpText() const { return ""; } //MainPage
|
||||
|
||||
void loadRequest(const TokenQueue *queue, const TokenRequest &req);
|
||||
|
||||
protected:
|
||||
virtual void updateDisplay(bool complete);
|
||||
|
||||
|
@ -62,9 +59,8 @@ private:
|
|||
void reloadAll();
|
||||
|
||||
void requestGroupMeta();
|
||||
void loadGroupMeta(const uint32_t &token);
|
||||
void loadGroupMeta(const std::list<RsGroupMetaData>& groupInfo);
|
||||
|
||||
TokenQueue *mCircleQueue;
|
||||
UIStateHelper *mStateHelper;
|
||||
|
||||
/* UI - from Designer */
|
||||
|
|
|
@ -358,7 +358,7 @@ void CreateCircleDialog::addMember(const QString& keyId, const QString& idtype,
|
|||
|
||||
tree->addTopLevelItem(member);
|
||||
|
||||
ui.members_groupBox->setTitle( tr("Invited Members") + " (" + QString::number(ui.treeWidget_membership->topLevelItemCount()) + ")" );
|
||||
updateMembership();
|
||||
}
|
||||
|
||||
/** Maybe we can use RsGxsCircleGroup instead of RsGxsCircleDetails ??? (TODO)**/
|
||||
|
@ -413,6 +413,8 @@ void CreateCircleDialog::removeMember()
|
|||
|
||||
// does this just work? (TODO)
|
||||
delete(item);
|
||||
|
||||
updateMembership();
|
||||
}
|
||||
|
||||
void CreateCircleDialog::createCircle()
|
||||
|
@ -584,9 +586,13 @@ void CreateCircleDialog::createCircle()
|
|||
circle.mMeta.mCircleType = GXS_CIRCLE_TYPE_LOCAL;
|
||||
}
|
||||
|
||||
uint32_t token;
|
||||
bool is_existing_circle(mIsExistingCircle);
|
||||
|
||||
if(mIsExistingCircle)
|
||||
RsThread::async([circle,is_existing_circle]()
|
||||
{
|
||||
RsGxsCircleId circleId;
|
||||
|
||||
if(is_existing_circle)
|
||||
{
|
||||
#ifdef DEBUG_CREATE_CIRCLE_DIALOG
|
||||
std::cerr << "CreateCircleDialog::updateCircle() : mCircleType: " << circle.mMeta.mCircleType << std::endl;
|
||||
|
@ -595,8 +601,9 @@ void CreateCircleDialog::createCircle()
|
|||
|
||||
std::cerr << "CreateCircleDialog::updateCircle() Checks and Balances Okay - calling service proper.."<< std::endl;
|
||||
#endif
|
||||
rsGxsCircles->editCircle(*const_cast<RsGxsCircleGroup*>(&circle)); // const_cast: Not nice, but simpler.
|
||||
|
||||
rsGxsCircles->updateGroup(token, circle);
|
||||
circleId = RsGxsCircleId(circle.mMeta.mGroupId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -606,10 +613,25 @@ void CreateCircleDialog::createCircle()
|
|||
|
||||
std::cerr << "CreateCircleDialog::createCircle() Checks and Balances Okay - calling service proper.."<< std::endl;
|
||||
#endif
|
||||
|
||||
rsGxsCircles->createGroup(token, circle);
|
||||
rsGxsCircles->createCircle(circle.mMeta.mGroupName,
|
||||
static_cast<RsGxsCircleType>(circle.mMeta.mCircleType),
|
||||
circleId,
|
||||
circle.mMeta.mCircleId,
|
||||
circle.mMeta.mAuthorId,
|
||||
circle.mInvitedMembers,
|
||||
circle.mLocalFriends);
|
||||
}
|
||||
|
||||
if(!is_existing_circle)
|
||||
RsQThreadUtils::postToObject( [circle,circleId]()
|
||||
{
|
||||
QMessageBox::information(nullptr,tr("Circle created"),
|
||||
tr("Your new circle has been created:\n Name: %1\n Id: %2.")
|
||||
.arg(QString::fromUtf8(circle.mMeta.mGroupName.c_str()))
|
||||
.arg(QString::fromStdString(circleId.toStdString())));
|
||||
});
|
||||
});
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -810,11 +832,6 @@ void CreateCircleDialog::loadIdentities()
|
|||
|
||||
void CreateCircleDialog::fillIdentitiesList(const std::vector<RsGxsIdGroup>& id_groups)
|
||||
{
|
||||
#ifdef DEBUG_CREATE_CIRCLE_DIALOG
|
||||
std::cerr << "CreateCircleDialog::loadIdentities(" << token << ")";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
QTreeWidget *tree = ui.treeWidget_IdList;
|
||||
tree->clear();
|
||||
|
||||
|
@ -937,3 +954,8 @@ void CreateCircleDialog::MembershipListCustomPopupMenu( QPoint )
|
|||
contextMnu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void CreateCircleDialog::updateMembership()
|
||||
{
|
||||
ui.members_groupBox->setTitle( tr("Invited Members") + " (" + QString::number(ui.treeWidget_membership->topLevelItemCount()) + ")" );
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ private slots:
|
|||
void filterChanged(const QString &text);
|
||||
void createNewGxsId();
|
||||
void idTypeChanged();
|
||||
void updateMembership();
|
||||
|
||||
/** Create the context popup menu and it's submenus */
|
||||
void IdListCustomPopupMenu( QPoint point );
|
||||
|
|
18
retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp
Normal file → Executable file
18
retroshare-gui/src/gui/FileTransfer/DLListDelegate.cpp
Normal file → Executable file
|
@ -32,6 +32,8 @@
|
|||
|
||||
Q_DECLARE_METATYPE(FileProgressInfo)
|
||||
|
||||
#define MAX_CHAR_TMP 128
|
||||
|
||||
DLListDelegate::DLListDelegate(QObject *parent) : QAbstractItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
@ -100,7 +102,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
|
|||
multi *= 1024.0;
|
||||
}
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignRight, temp);
|
||||
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp);
|
||||
break;
|
||||
case COLUMN_REMAINING:
|
||||
remaining = index.data().toLongLong();
|
||||
|
@ -119,7 +121,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
|
|||
multi *= 1024.0;
|
||||
}
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignRight, temp);
|
||||
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp);
|
||||
break;
|
||||
case COLUMN_COMPLETED:
|
||||
completed = index.data().toLongLong();
|
||||
|
@ -138,7 +140,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
|
|||
multi *= 1024.0;
|
||||
}
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignRight, temp);
|
||||
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp);
|
||||
break;
|
||||
case COLUMN_DLSPEED:
|
||||
dlspeed = index.data().toDouble();
|
||||
|
@ -149,7 +151,7 @@ void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & opti
|
|||
temp.sprintf("%.2f", dlspeed/1024.);
|
||||
temp += " KB/s";
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignRight, temp);
|
||||
painter->drawText(option.rect, Qt::AlignRight | Qt::AlignVCenter, temp);
|
||||
break;
|
||||
case COLUMN_PROGRESS:
|
||||
{
|
||||
|
@ -234,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);
|
||||
pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
|
||||
if (pixmapRect.isValid()){
|
||||
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
|
||||
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft();
|
||||
p.setX( p.x() + pixOffset);
|
||||
painter->drawPixmap(p, pixmap);
|
||||
temp = " " + temp;
|
||||
|
@ -245,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);
|
||||
pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
|
||||
if (pixmapRect.isValid()){
|
||||
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
|
||||
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter, pixmap.size(), option.rect).topLeft();
|
||||
p.setX( p.x() + pixOffset);
|
||||
painter->drawPixmap(p, pixmap);
|
||||
temp = " " + temp;
|
||||
pixOffset += pixmap.size().width();
|
||||
}
|
||||
painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft, temp);
|
||||
painter->drawText(option.rect.translated(pixOffset, 0), Qt::AlignLeft | Qt::AlignVCenter, temp);
|
||||
}
|
||||
break;
|
||||
case COLUMN_LASTDL:
|
||||
|
@ -277,7 +279,7 @@ QSize DLListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModel
|
|||
{
|
||||
float w = QFontMetricsF(option.font).width(index.data(Qt::DisplayRole).toString());
|
||||
|
||||
int S = QFontMetricsF(option.font).height() ;
|
||||
int S = QFontMetricsF(option.font).height()*1.5 ;
|
||||
return QSize(w,S);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,55 +18,40 @@
|
|||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef DLLISTDELEGATE_H
|
||||
#define DLLISTDELEGATE_H
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemDelegate>
|
||||
#include "xprogressbar.h"
|
||||
|
||||
|
||||
// Defines for download list list columns
|
||||
#define COLUMN_NAME 0
|
||||
#define COLUMN_SIZE 1
|
||||
#define COLUMN_COMPLETED 2
|
||||
#define COLUMN_DLSPEED 3
|
||||
#define COLUMN_PROGRESS 4
|
||||
#define COLUMN_SOURCES 5
|
||||
#define COLUMN_STATUS 6
|
||||
#define COLUMN_PRIORITY 7
|
||||
#define COLUMN_REMAINING 8
|
||||
#define COLUMN_DOWNLOADTIME 9
|
||||
#define COLUMN_ID 10
|
||||
#define COLUMN_LASTDL 11
|
||||
#define COLUMN_PATH 12
|
||||
#define COLUMN_COUNT 13
|
||||
|
||||
#define PRIORITY_NULL 0.0
|
||||
#define PRIORITY_FASTER 0.1
|
||||
#define PRIORITY_AVERAGE 0.2
|
||||
#define PRIORITY_SLOWER 0.3
|
||||
|
||||
#define MAX_CHAR_TMP 128
|
||||
|
||||
class QModelIndex;
|
||||
class QPainter;
|
||||
|
||||
|
||||
class DLListDelegate: public QAbstractItemDelegate {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
class DLListDelegate: public QAbstractItemDelegate
|
||||
{
|
||||
public:
|
||||
DLListDelegate(QObject *parent=0);
|
||||
virtual ~DLListDelegate(){}
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const;
|
||||
|
||||
private:
|
||||
static constexpr int COLUMN_NAME = 0;
|
||||
static constexpr int COLUMN_SIZE = 1;
|
||||
static constexpr int COLUMN_COMPLETED = 2;
|
||||
static constexpr int COLUMN_DLSPEED = 3;
|
||||
static constexpr int COLUMN_PROGRESS = 4;
|
||||
static constexpr int COLUMN_SOURCES = 5;
|
||||
static constexpr int COLUMN_STATUS = 6;
|
||||
static constexpr int COLUMN_PRIORITY = 7;
|
||||
static constexpr int COLUMN_REMAINING = 8;
|
||||
static constexpr int COLUMN_DOWNLOADTIME= 9;
|
||||
static constexpr int COLUMN_ID = 10;
|
||||
static constexpr int COLUMN_LASTDL = 11;
|
||||
static constexpr int COLUMN_PATH = 12;
|
||||
static constexpr int COLUMN_COUNT = 13;
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
static constexpr float PRIORITY_NULL = 0.0;
|
||||
static constexpr float PRIORITY_FASTER = 0.1;
|
||||
static constexpr float PRIORITY_AVERAGE = 0.2;
|
||||
static constexpr float PRIORITY_SLOWER = 0.3;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,13 +30,14 @@
|
|||
#include "gui/RetroShareLink.h"
|
||||
#include "retroshare-gui/RsAutoUpdatePage.h"
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
#include "gui/common/RsCollection.h"
|
||||
#include "gui/common/RsCollectionDialog.h"
|
||||
#include "gui/common/FilesDefs.h"
|
||||
#include "gui/common/RsUrlHandler.h"
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
#include "gui/advsearch/advancedsearchdialog.h"
|
||||
#include "gui/common/RSTreeWidgetItem.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "util/qtthreadsutils.h"
|
||||
|
||||
#include <retroshare/rsfiles.h>
|
||||
#include <retroshare/rsturtle.h>
|
||||
|
@ -85,6 +86,18 @@ const int SearchDialog::FILETYPE_IDX_DIRECTORY = 8;
|
|||
QMap<int, QString> * SearchDialog::FileTypeExtensionMap = new QMap<int, QString>();
|
||||
bool SearchDialog::initialised = false;
|
||||
|
||||
struct SearchDialog::FileDetail
|
||||
{
|
||||
public:
|
||||
RsPeerId id;
|
||||
std::string name;
|
||||
RsFileHash hash;
|
||||
std::string path;
|
||||
uint64_t size;
|
||||
uint32_t mtime;
|
||||
uint32_t rank;
|
||||
};
|
||||
|
||||
/** Constructor */
|
||||
SearchDialog::SearchDialog(QWidget *parent)
|
||||
: MainPage(parent),
|
||||
|
@ -188,6 +201,10 @@ SearchDialog::SearchDialog(QWidget *parent)
|
|||
|
||||
ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder);
|
||||
|
||||
QFontMetricsF fontMetrics(ui.searchResultWidget->font());
|
||||
int iconHeight = fontMetrics.height() * 1.4;
|
||||
ui.searchResultWidget->setIconSize(QSize(iconHeight, iconHeight));
|
||||
|
||||
/* Set initial size the splitter */
|
||||
QList<int> sizes;
|
||||
sizes << 250 << width(); // Qt calculates the right sizes
|
||||
|
@ -213,6 +230,15 @@ SearchDialog::SearchDialog(QWidget *parent)
|
|||
|
||||
checkText(ui.lineEdit->text());
|
||||
|
||||
// add an event handler to get search results (previously available through notifyQt)
|
||||
|
||||
mEventHandlerId = 0;
|
||||
|
||||
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event)
|
||||
{
|
||||
RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this );
|
||||
}, mEventHandlerId, RsEventType::FILE_TRANSFER );
|
||||
|
||||
}
|
||||
|
||||
SearchDialog::~SearchDialog()
|
||||
|
@ -231,6 +257,31 @@ SearchDialog::~SearchDialog()
|
|||
|
||||
ui.searchResultWidget->setItemDelegateForColumn(SR_SIZE_COL, nullptr);
|
||||
ui.searchResultWidget->setItemDelegateForColumn(SR_AGE_COL, nullptr);
|
||||
|
||||
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||
}
|
||||
|
||||
void SearchDialog::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
|
||||
{
|
||||
if(event->mType != RsEventType::FILE_TRANSFER)
|
||||
return;
|
||||
|
||||
auto fe = dynamic_cast<const RsFileTransferEvent*>(event.get());
|
||||
|
||||
if(!fe || fe->mFileTransferEventCode!=RsFileTransferEventCode::NEW_DISTANT_SEARCH_RESULTS)
|
||||
return;
|
||||
|
||||
for(uint32_t i=0;i<fe->mResults.size();++i)
|
||||
{
|
||||
FileDetail f;
|
||||
f.hash = fe->mResults[i].fHash;
|
||||
f.name = fe->mResults[i].fName;
|
||||
f.size = fe->mResults[i].fSize;
|
||||
f.mtime = 0; // zero what's not available, otherwise we'll get some random values displayed.
|
||||
f.rank = 0;
|
||||
|
||||
updateFiles(fe->mRequestId,f);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchDialog::processSettings(bool bLoad)
|
||||
|
@ -274,7 +325,7 @@ void SearchDialog::checkText(const QString& txt)
|
|||
ui.searchButton->setDisabled(txt.length() < 3);
|
||||
ui.searchLineFrame->setProperty("valid", (txt.length() >= 3));
|
||||
ui.searchLineFrame->style()->unpolish(ui.searchLineFrame);
|
||||
Rshare::refreshStyleSheet(ui.searchLineFrame, false);
|
||||
RsApplication::refreshStyleSheet(ui.searchLineFrame, false);
|
||||
}
|
||||
|
||||
void SearchDialog::initialiseFileTypeMappings()
|
||||
|
@ -282,7 +333,7 @@ void SearchDialog::initialiseFileTypeMappings()
|
|||
/* edit these strings to change the range of extensions recognised by the search */
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ANY, "");
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO,
|
||||
"aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma");
|
||||
"aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma weba");
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE,
|
||||
"7z bz2 gz pkg rar sea sit sitx tar zip tgz");
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE,
|
||||
|
@ -291,11 +342,11 @@ void SearchDialog::initialiseFileTypeMappings()
|
|||
"doc odt ott rtf pdf ps txt log msg wpd wps ods xls epub" );
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE,
|
||||
"3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm "
|
||||
"pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf");
|
||||
"pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf webp");
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM,
|
||||
"app bat cgi com bin exe js pif py pl sh vb ws bash");
|
||||
SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO,
|
||||
"3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv");
|
||||
"3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv webm");
|
||||
SearchDialog::initialised = true;
|
||||
}
|
||||
|
||||
|
@ -446,25 +497,23 @@ void SearchDialog::collCreate()
|
|||
int selectedCount = selectedItems.size() ;
|
||||
QTreeWidgetItem * item ;
|
||||
|
||||
for (int i = 0; i < selectedCount; ++i) {
|
||||
RsFileTree tree;
|
||||
|
||||
for (int i = 0; i < selectedCount; ++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();
|
||||
RsFileHash hash( item->text(SR_HASH_COL).toStdString() );
|
||||
uint64_t count = item->text(SR_SIZE_COL).toULongLong();
|
||||
|
||||
DirDetails details;
|
||||
details.name = name;
|
||||
details.hash = hash;
|
||||
details.size = count;
|
||||
details.type = DIR_TYPE_FILE;
|
||||
|
||||
dirVec.push_back(details);
|
||||
tree.addFile(tree.root(),name,hash,count);
|
||||
}
|
||||
}
|
||||
|
||||
RsCollection(dirVec,RS_FILE_HINTS_LOCAL).openNewColl(this);
|
||||
RsCollectionDialog::openNewCollection(tree);
|
||||
}
|
||||
|
||||
void SearchDialog::collModif()
|
||||
|
@ -491,12 +540,8 @@ void SearchDialog::collModif()
|
|||
/* open file with a suitable application */
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
|
||||
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath());
|
||||
}
|
||||
|
||||
void SearchDialog::collView()
|
||||
|
@ -523,12 +568,8 @@ void SearchDialog::collView()
|
|||
/* open file with a suitable application */
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath(), true);
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
|
||||
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true);
|
||||
}
|
||||
|
||||
void SearchDialog::collOpen()
|
||||
|
@ -546,32 +587,35 @@ void SearchDialog::collOpen()
|
|||
|
||||
if (rsFiles->FileDetails(hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL
|
||||
| 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 */
|
||||
std::string path;
|
||||
path = info.path;
|
||||
|
||||
/* open file with a suitable application */
|
||||
QFileInfo qinfo;
|
||||
RsCollection::RsCollectionErrorCode err;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
if (collection.load(qinfo.absoluteFilePath())) {
|
||||
collection.downloadFiles();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
|
||||
RsCollectionDialog::downloadFiles(RsCollection(qinfo.absoluteFilePath(),err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RsCollection collection;
|
||||
if (collection.load(this)) {
|
||||
collection.downloadFiles();
|
||||
}//if (collection.load(this))
|
||||
QString fileName;
|
||||
if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
|
||||
return ;
|
||||
|
||||
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)
|
||||
|
@ -801,28 +845,29 @@ void SearchDialog::advancedSearch(RsRegularExpression::Expression* expression)
|
|||
{
|
||||
advSearchDialog->hide();
|
||||
|
||||
/* call to core */
|
||||
std::list<DirDetails> results;
|
||||
|
||||
// send a turtle search request
|
||||
RsRegularExpression::LinearizedExpression e ;
|
||||
expression->linearize(e) ;
|
||||
|
||||
TurtleRequestId req_id = rsFiles->turtleSearch(e) ;
|
||||
TurtleRequestId req_id ;
|
||||
|
||||
if(ui._anonF2Fsearch_CB->isChecked())
|
||||
req_id = rsFiles->turtleSearch(e) ;
|
||||
else
|
||||
req_id = RSRandom::random_u32() ; // generate a random 32 bits request id
|
||||
|
||||
// This will act before turtle results come to the interface, thanks to the signals scheduling policy.
|
||||
initSearchResult(QString::fromStdString(e.GetStrings()),req_id, ui.FileTypeComboBox->currentIndex(), true) ;
|
||||
|
||||
rsFiles -> SearchBoolExp(expression, results, RS_FILE_HINTS_REMOTE);// | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE);
|
||||
std::list<DirDetails> results;
|
||||
|
||||
FileSearchFlags flags(0);
|
||||
if(ui._ownFiles_CB->isChecked()) flags |= RS_FILE_HINTS_LOCAL;
|
||||
if(ui._friendListsearch_SB->isChecked()) flags |= RS_FILE_HINTS_REMOTE;
|
||||
|
||||
rsFiles -> SearchBoolExp(expression, results, flags);
|
||||
|
||||
/* abstraction to allow reusee of tree rendering code */
|
||||
resultsToTree(advSearchDialog->getSearchAsString(),req_id, results);
|
||||
|
||||
// // debug stuff
|
||||
// Expression *expression2 = LinearizedExpression::toExpr(e) ;
|
||||
// results.clear() ;
|
||||
// rsFiles -> SearchBoolExp(expression2, results, DIR_FLAGS_REMOTE | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE);
|
||||
// resultsToTree((advSearchDialog->getSearchAsString()).toStdString(),req_id+1, results);
|
||||
}
|
||||
|
||||
void SearchDialog::searchKeywords()
|
||||
|
@ -928,7 +973,7 @@ void SearchDialog::searchKeywords(const QString& keywords)
|
|||
}
|
||||
}
|
||||
|
||||
void SearchDialog::updateFiles(qulonglong search_id,FileDetail file)
|
||||
void SearchDialog::updateFiles(qulonglong search_id,const FileDetail& file)
|
||||
{
|
||||
searchResultsQueue.push_back(std::pair<qulonglong,FileDetail>(search_id,file)) ;
|
||||
|
||||
|
@ -956,7 +1001,7 @@ void SearchDialog::processResultQueue()
|
|||
while(!searchResultsQueue.empty() && nb_treated_elements++ < 250)
|
||||
{
|
||||
qulonglong search_id = searchResultsQueue.back().first ;
|
||||
FileDetail& file = searchResultsQueue.back().second ;
|
||||
const FileDetail& file = searchResultsQueue.back().second ;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << "Updating file detail:" << std::endl ;
|
||||
|
@ -1282,8 +1327,8 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s
|
|||
|
||||
item->setText(SR_SIZE_COL, QString::number(file.size));
|
||||
item->setData(SR_SIZE_COL, ROLE_SORT, (qulonglong) file.size);
|
||||
item->setText(SR_AGE_COL, QString::number(file.age));
|
||||
item->setData(SR_AGE_COL, ROLE_SORT, file.age);
|
||||
item->setText(SR_AGE_COL, QString::number(file.mtime));
|
||||
item->setData(SR_AGE_COL, ROLE_SORT, file.mtime);
|
||||
item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight );
|
||||
int friendSource = 0;
|
||||
int anonymousSource = 0;
|
||||
|
@ -1358,21 +1403,21 @@ void SearchDialog::resultsToTree(const QString& txt,qulonglong searchId, const s
|
|||
|
||||
std::list<DirDetails>::const_iterator it;
|
||||
for(it = results.begin(); it != results.end(); ++it)
|
||||
if (it->type == DIR_TYPE_FILE) {
|
||||
if (it->type == DIR_TYPE_FILE)
|
||||
{
|
||||
FileDetail fd;
|
||||
fd.id = it->id;
|
||||
fd.name = it->name;
|
||||
fd.hash = it->hash;
|
||||
fd.path = it->path;
|
||||
fd.size = it->size;
|
||||
fd.age = it->mtime;
|
||||
fd.mtime= it->mtime;
|
||||
fd.rank = 0;
|
||||
|
||||
insertFile(searchId,fd, FRIEND_SEARCH);
|
||||
} else if (it->type == DIR_TYPE_DIR) {
|
||||
// insertDirectory(txt, searchId, *it, NULL);
|
||||
insertDirectory(txt, searchId, *it);
|
||||
}
|
||||
else if (it->type == DIR_TYPE_DIR)
|
||||
insertDirectory(txt, searchId, *it);
|
||||
|
||||
ui.searchResultWidget->setSortingEnabled(true);
|
||||
}
|
||||
|
@ -1451,32 +1496,37 @@ void SearchDialog::copyResultLink()
|
|||
{
|
||||
/* should also be able to handle multi-selection */
|
||||
QList<QTreeWidgetItem*> itemsForCopy = ui.searchResultWidget->selectedItems();
|
||||
int numdls = itemsForCopy.size();
|
||||
QTreeWidgetItem * item;
|
||||
|
||||
std::set<RsFileHash> already_seen_hashes;
|
||||
QList<RetroShareLink> urls ;
|
||||
|
||||
for (int i = 0; i < numdls; ++i)
|
||||
for (auto item:itemsForCopy)
|
||||
{
|
||||
item = itemsForCopy.at(i);
|
||||
// call copy
|
||||
|
||||
if (!item->childCount())
|
||||
QString fhash = item->text(SR_HASH_COL);
|
||||
RsFileHash hash(fhash.toStdString());
|
||||
|
||||
if(!hash.isNull() && (already_seen_hashes.end() == already_seen_hashes.find(hash)))
|
||||
{
|
||||
std::cerr << "SearchDialog::copyResultLink() Calling set retroshare link";
|
||||
std::cerr << std::endl;
|
||||
|
||||
QString fhash = item->text(SR_HASH_COL);
|
||||
qulonglong fsize = item->text(SR_SIZE_COL).toULongLong();
|
||||
QString fname = item->text(SR_NAME_COL);
|
||||
|
||||
RetroShareLink link = RetroShareLink::createFile(fname, fsize, fhash);
|
||||
if (link.valid()) {
|
||||
|
||||
if (link.valid())
|
||||
{
|
||||
std::cerr << "new link added to clipboard: " << link.toString().toStdString() << std::endl ;
|
||||
urls.push_back(link);
|
||||
already_seen_hashes.insert(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!urls.empty())
|
||||
RSLinkClipboard::copyLinks(urls) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
#ifndef _SEARCHDIALOG_H
|
||||
#define _SEARCHDIALOG_H
|
||||
|
||||
#include <retroshare/rstypes.h>
|
||||
#include "retroshare/rstypes.h"
|
||||
#include "retroshare/rsevents.h"
|
||||
#include "ui_SearchDialog.h"
|
||||
#include <retroshare-gui/mainpage.h>
|
||||
#include "retroshare-gui/mainpage.h"
|
||||
|
||||
class AdvancedSearchDialog;
|
||||
class RSTreeWidgetItemCompareRole;
|
||||
|
@ -42,6 +43,7 @@ class SearchDialog : public MainPage
|
|||
Q_PROPERTY(QColor textColorLowSources READ textColorLowSources WRITE setTextColorLowSources)
|
||||
Q_PROPERTY(QColor textColorHighSources READ textColorHighSources WRITE setTextColorHighSources)
|
||||
|
||||
struct FileDetail; // useful structure to store search results.
|
||||
public:
|
||||
/** Default Constructor */
|
||||
SearchDialog(QWidget *parent = 0);
|
||||
|
@ -62,8 +64,7 @@ public:
|
|||
void setTextColorLowSources(QColor color) { mTextColorLowSources = color; }
|
||||
void setTextColorHighSources(QColor color) { mTextColorHighSources = color; }
|
||||
|
||||
public slots:
|
||||
void updateFiles(qulonglong request_id,FileDetail file) ;
|
||||
void updateFiles(qulonglong request_id, const FileDetail& file) ;
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -125,6 +126,7 @@ private:
|
|||
void setIconAndType(QTreeWidgetItem *item, const QString& filename);
|
||||
void downloadDirectory(const QTreeWidgetItem *item, const QString &base);
|
||||
void getSourceFriendsForHash(const RsFileHash &hash,std::list<RsPeerId> &srcIds);
|
||||
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
||||
|
||||
/** the advanced search dialog instance */
|
||||
AdvancedSearchDialog * advSearchDialog;
|
||||
|
@ -176,6 +178,8 @@ private:
|
|||
|
||||
bool _queueIsAlreadyTakenCareOf ;
|
||||
std::vector<std::pair<qulonglong,FileDetail> > searchResultsQueue ;
|
||||
|
||||
RsEventsHandlerId_t mEventHandlerId ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>783</width>
|
||||
<width>793</width>
|
||||
<height>511</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -64,10 +64,7 @@
|
|||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
|
@ -343,8 +340,8 @@
|
|||
<string>Any</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeAny.png</normaloff>:/images/FileTypeAny.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/any.svg</normaloff>:/icons/filetype/any.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -352,8 +349,8 @@
|
|||
<string>Archive</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeArchive.png</normaloff>:/images/FileTypeArchive.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/archive.svg</normaloff>:/icons/filetype/archive.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -361,8 +358,8 @@
|
|||
<string>Audio</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeAudio.png</normaloff>:/images/FileTypeAudio.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/audio.svg</normaloff>:/icons/filetype/audio.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -370,8 +367,8 @@
|
|||
<string>CD-Image</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeCDImage.png</normaloff>:/images/FileTypeCDImage.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/img.svg</normaloff>:/icons/filetype/img.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -379,8 +376,8 @@
|
|||
<string>Document</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeDocument.png</normaloff>:/images/FileTypeDocument.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/document.svg</normaloff>:/icons/filetype/document.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -388,8 +385,8 @@
|
|||
<string>Picture</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypePicture.png</normaloff>:/images/FileTypePicture.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/picture.svg</normaloff>:/icons/filetype/picture.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -397,8 +394,8 @@
|
|||
<string>Program</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeProgram.png</normaloff>:/images/FileTypeProgram.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/program.svg</normaloff>:/icons/filetype/program.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -406,8 +403,8 @@
|
|||
<string>Video</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/FileTypeVideo.png</normaloff>:/images/FileTypeVideo.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/filetype/video.svg</normaloff>:/icons/filetype/video.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -415,8 +412,8 @@
|
|||
<string>Directory</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/foldermail.png</normaloff>:/images/foldermail.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/folder.png</normaloff>:/icons/folder.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "gui/RetroShareLink.h"
|
||||
#include "gui/ShareManager.h"
|
||||
#include "gui/common/PeerDefs.h"
|
||||
#include "gui/common/RsCollection.h"
|
||||
#include "gui/common/RsCollectionDialog.h"
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
#include "gui/gxschannels/GxsChannelDialog.h"
|
||||
#include "gui/gxsforums/GxsForumsDialog.h"
|
||||
|
@ -55,6 +55,16 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
#define SHARED_FILES_DIALOG_COLUMN_NAME 0
|
||||
#define SHARED_FILES_DIALOG_COLUMN_FILENB 1
|
||||
#define SHARED_FILES_DIALOG_COLUMN_SIZE 2
|
||||
#define SHARED_FILES_DIALOG_COLUMN_AGE 3
|
||||
#define SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS 4
|
||||
#define SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR 5
|
||||
#define SHARED_FILES_DIALOG_COLUMN_COUNT 6
|
||||
|
||||
#define SHARED_FILES_DIALOG_FILTER_STRING "filtered"
|
||||
|
||||
/* Images for context menu icons */
|
||||
#define IMAGE_DOWNLOAD ":/icons/png/download.png"
|
||||
#define IMAGE_PLAY ":/images/start.png"
|
||||
|
@ -75,7 +85,7 @@
|
|||
#define IMAGE_COLLOPEN ":/icons/collections.png"
|
||||
#define IMAGE_EDITSHARE ":/icons/png/pencil-edit-button.png"
|
||||
#define IMAGE_MYFILES ":/icons/svg/folders1.svg"
|
||||
#define IMAGE_UNSHAREEXTRA ":/images/button_cancel.png"
|
||||
#define IMAGE_UNSHAREEXTRA ":/icons/cancel.svg"
|
||||
|
||||
/*define viewType_CB value */
|
||||
#define VIEW_TYPE_TREE 0
|
||||
|
@ -91,7 +101,7 @@
|
|||
|
||||
//#define DEBUG_SHARED_FILES_DIALOG 1
|
||||
|
||||
const QString Image_AddNewAssotiationForFile = ":/images/kcmsystem24.png";
|
||||
const QString Image_AddNewAssotiationForFile = ":/icons/svg/options.svg";
|
||||
|
||||
class SFDSortFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
|
@ -187,17 +197,17 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
tree_proxyModel->setSourceModel(tree_model);
|
||||
tree_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
tree_proxyModel->setSortRole(RetroshareDirModel::SortRole);
|
||||
tree_proxyModel->sort(COLUMN_NAME);
|
||||
tree_proxyModel->sort(SHARED_FILES_DIALOG_COLUMN_NAME);
|
||||
tree_proxyModel->setFilterRole(RetroshareDirModel::FilterRole);
|
||||
tree_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ;
|
||||
tree_proxyModel->setFilterRegExp(QRegExp(QString(SHARED_FILES_DIALOG_FILTER_STRING))) ;
|
||||
|
||||
flat_proxyModel = new SFDSortFilterProxyModel(flat_model, this);
|
||||
flat_proxyModel->setSourceModel(flat_model);
|
||||
flat_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
flat_proxyModel->setSortRole(RetroshareDirModel::SortRole);
|
||||
flat_proxyModel->sort(COLUMN_NAME);
|
||||
flat_proxyModel->sort(SHARED_FILES_DIALOG_COLUMN_NAME);
|
||||
flat_proxyModel->setFilterRole(RetroshareDirModel::FilterRole);
|
||||
flat_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ;
|
||||
flat_proxyModel->setFilterRegExp(QRegExp(QString(SHARED_FILES_DIALOG_FILTER_STRING))) ;
|
||||
|
||||
connect(ui.filterClearButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
|
||||
connect(ui.filterStartButton, SIGNAL(clicked()), this, SLOT(startFilter()));
|
||||
|
@ -219,12 +229,12 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
int charWidth = ui.dirTreeView->fontMetrics().horizontalAdvance("_");
|
||||
#endif
|
||||
|
||||
header->resizeSection ( COLUMN_NAME , charWidth*100 );
|
||||
header->resizeSection ( COLUMN_FILENB , charWidth*15 );
|
||||
header->resizeSection ( COLUMN_SIZE , charWidth*10 );
|
||||
header->resizeSection ( COLUMN_AGE , charWidth*6 );
|
||||
header->resizeSection ( COLUMN_FRIEND_ACCESS, charWidth*10 );
|
||||
header->resizeSection ( COLUMN_WN_VISU_DIR , charWidth*20 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_NAME , charWidth*100 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FILENB , charWidth*15 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_SIZE , charWidth*10 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_AGE , charWidth*6 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, charWidth*10 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR , charWidth*20 );
|
||||
|
||||
header->setStretchLastSection(true);
|
||||
|
||||
|
@ -256,7 +266,7 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent)
|
|||
: SharedFilesDialog(false,parent)
|
||||
{
|
||||
// Hide columns after loading the settings
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.downloadButton->hide() ;
|
||||
|
||||
// load settings
|
||||
|
@ -275,14 +285,14 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent)
|
|||
|
||||
ui.titleBarPixmap->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_MYFILES)) ;
|
||||
|
||||
ui.dirTreeView->setItemDelegateForColumn(COLUMN_FRIEND_ACCESS,new ShareFlagsItemDelegate()) ;
|
||||
ui.dirTreeView->setItemDelegateForColumn(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS,new ShareFlagsItemDelegate()) ;
|
||||
}
|
||||
|
||||
RemoteSharedFilesDialog::RemoteSharedFilesDialog(QWidget *parent)
|
||||
: SharedFilesDialog(true,parent)
|
||||
{
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, true) ;
|
||||
ui.checkButton->hide() ;
|
||||
|
||||
connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadRemoteSelected()));
|
||||
|
@ -309,7 +319,7 @@ void SharedFilesDialog::hideEvent(QHideEvent *)
|
|||
model->setVisible(false) ;
|
||||
}
|
||||
|
||||
void SharedFilesDialog::showEvent(QShowEvent *)
|
||||
void SharedFilesDialog::showEvent(QShowEvent *event)
|
||||
{
|
||||
if(model!=NULL)
|
||||
{
|
||||
|
@ -322,6 +332,10 @@ void SharedFilesDialog::showEvent(QShowEvent *)
|
|||
|
||||
restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes);
|
||||
}
|
||||
|
||||
if (!event->spontaneous()) {
|
||||
updateFontSize();
|
||||
}
|
||||
}
|
||||
RemoteSharedFilesDialog::~RemoteSharedFilesDialog()
|
||||
{
|
||||
|
@ -436,9 +450,9 @@ void SharedFilesDialog::changeCurrentViewModel(int viewTypeIndex)
|
|||
restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes);
|
||||
|
||||
QHeaderView * header = ui.dirTreeView->header () ;
|
||||
QHeaderView_setSectionResizeModeColumn(header, COLUMN_NAME, QHeaderView::Interactive);
|
||||
QHeaderView_setSectionResizeModeColumn(header, SHARED_FILES_DIALOG_COLUMN_NAME, QHeaderView::Interactive);
|
||||
|
||||
ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, COLUMN_NAME, COLUMN_WN_VISU_DIR) ;
|
||||
ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, SHARED_FILES_DIALOG_COLUMN_NAME, SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR) ;
|
||||
|
||||
// recursRestoreExpandedItems(ui.dirTreeView->rootIndex(),expanded_indexes);
|
||||
FilterItems();
|
||||
|
@ -448,9 +462,9 @@ void LocalSharedFilesDialog::showProperColumns()
|
|||
{
|
||||
if(model == tree_model)
|
||||
{
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ;
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
ui.filterLabel->hide();
|
||||
ui.filterPatternLineEdit->hide();
|
||||
|
@ -460,9 +474,9 @@ void LocalSharedFilesDialog::showProperColumns()
|
|||
}
|
||||
else
|
||||
{
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, true) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, true) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ;
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
ui.filterLabel->show();
|
||||
ui.filterPatternLineEdit->show();
|
||||
|
@ -473,9 +487,9 @@ void RemoteSharedFilesDialog::showProperColumns()
|
|||
{
|
||||
if(model == tree_model)
|
||||
{
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, true) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, true) ;
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
ui.filterLabel->hide();
|
||||
ui.filterPatternLineEdit->hide();
|
||||
|
@ -485,9 +499,9 @@ void RemoteSharedFilesDialog::showProperColumns()
|
|||
}
|
||||
else
|
||||
{
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, true) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FILENB, true) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, false) ;
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ;
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
ui.filterLabel->show();
|
||||
ui.filterPatternLineEdit->show();
|
||||
|
@ -515,7 +529,6 @@ void LocalSharedFilesDialog::checkUpdate()
|
|||
void LocalSharedFilesDialog::forceCheck()
|
||||
{
|
||||
rsFiles->ForceDirectoryCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
||||
|
@ -639,7 +652,7 @@ void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<
|
|||
|
||||
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
|
||||
|
||||
RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ;
|
||||
RetroShareLink link = RetroShareLink::createFileTree(dir_name,ft->totalFileSize(),ft->numFiles(),QString::fromStdString(ft->toRadix64())) ;
|
||||
|
||||
if(link.valid())
|
||||
urls.push_back(link) ;
|
||||
|
@ -721,7 +734,32 @@ void SharedFilesDialog::sendLinkTo()
|
|||
void SharedFilesDialog::collCreate()
|
||||
{
|
||||
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()
|
||||
|
@ -746,12 +784,8 @@ void SharedFilesDialog::collModif()
|
|||
/* open file with a suitable application */
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
|
||||
RsCollectionDialog::editExistingCollection(qinfo.absoluteFilePath());
|
||||
}
|
||||
|
||||
void SharedFilesDialog::collView()
|
||||
|
@ -776,12 +810,8 @@ void SharedFilesDialog::collView()
|
|||
/* open file with a suitable application */
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath(), true);
|
||||
}
|
||||
}
|
||||
if (qinfo.exists() && qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString))
|
||||
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(), true);
|
||||
}
|
||||
|
||||
void SharedFilesDialog::collOpen()
|
||||
|
@ -808,20 +838,24 @@ void SharedFilesDialog::collOpen()
|
|||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
if (collection.load(qinfo.absoluteFilePath())) {
|
||||
collection.downloadFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
RsCollectionDialog::openExistingCollection(qinfo.absoluteFilePath(),true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RsCollection collection;
|
||||
if (collection.load(this)) {
|
||||
collection.downloadFiles();
|
||||
}
|
||||
QString fileName;
|
||||
if (!misc::getOpenFileName(nullptr, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
|
||||
return ;
|
||||
|
||||
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()
|
||||
|
@ -1132,12 +1166,14 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
|||
collViewAct->setEnabled(bIsRsColl);
|
||||
collOpenAct->setEnabled(true);
|
||||
|
||||
QMenu collectionMenu(tr("Collection"), this);
|
||||
QMenu collectionMenu(tr("Retroshare Collection"), this);
|
||||
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
|
||||
collectionMenu.addAction(collCreateAct);
|
||||
|
||||
if(bIsRsColl)
|
||||
collectionMenu.addAction(collModifAct);
|
||||
collectionMenu.addAction(collViewAct);
|
||||
collectionMenu.addAction(collOpenAct);
|
||||
//collectionMenu.addAction(collViewAct);
|
||||
//collectionMenu.addAction(collOpenAct);
|
||||
|
||||
switch (type) {
|
||||
case DIR_TYPE_DIR :
|
||||
|
@ -1333,9 +1369,9 @@ void SharedFilesDialog::indicatorChanged(int index)
|
|||
ui.dirTreeView->update(ui.dirTreeView->rootIndex());
|
||||
|
||||
if (correct_indicator[index] != IND_ALWAYS)
|
||||
ui.dirTreeView->sortByColumn(COLUMN_AGE, Qt::AscendingOrder);
|
||||
ui.dirTreeView->sortByColumn(SHARED_FILES_DIALOG_COLUMN_AGE, Qt::AscendingOrder);
|
||||
else
|
||||
ui.dirTreeView->sortByColumn(COLUMN_NAME, Qt::AscendingOrder);
|
||||
ui.dirTreeView->sortByColumn(SHARED_FILES_DIALOG_COLUMN_NAME, Qt::AscendingOrder);
|
||||
|
||||
updateDisplay() ;
|
||||
}
|
||||
|
@ -1672,3 +1708,20 @@ bool SharedFilesDialog::tree_FilterItem(const QModelIndex &index, const QString
|
|||
return (visible || visibleChildCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
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();
|
||||
#endif
|
||||
QFont newFont = ui.dirTreeView->font();
|
||||
if (newFont.pointSize() != customFontSize) {
|
||||
newFont.setPointSize(customFontSize);
|
||||
QFontMetricsF fontMetrics(newFont);
|
||||
int iconHeight = fontMetrics.height()*1.5;
|
||||
ui.dirTreeView->setFont(newFont);
|
||||
ui.dirTreeView->setIconSize(QSize(iconHeight, iconHeight));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,8 @@ protected:
|
|||
|
||||
QModelIndexList getSelected();
|
||||
|
||||
void updateFontSize();
|
||||
|
||||
/** Defines the actions for the context menu for QTreeWidget */
|
||||
QAction* copylinkAct;
|
||||
QAction* sendlinkAct;
|
||||
|
|
|
@ -243,8 +243,8 @@ border-image: url(:/images/closepressed.png)
|
|||
<string>All</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/view_calendar_list.png</normaloff>:/images/view_calendar_list.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/svg/calendar-blank.svg</normaloff>:/icons/svg/calendar-blank.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -252,8 +252,8 @@ border-image: url(:/images/closepressed.png)
|
|||
<string>One day old</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/view_calendar_day.png</normaloff>:/images/view_calendar_day.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/svg/calendar-today.svg</normaloff>:/icons/svg/calendar-today.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -261,8 +261,8 @@ border-image: url(:/images/closepressed.png)
|
|||
<string>One Week old</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/view_calendar_week.png</normaloff>:/images/view_calendar_week.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/svg/calendar-week.svg</normaloff>:/icons/svg/calendar-week.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -270,8 +270,8 @@ border-image: url(:/images/closepressed.png)
|
|||
<string>One month old</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/view_calendar_month.png</normaloff>:/images/view_calendar_month.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/svg/calendar-month.svg</normaloff>:/icons/svg/calendar-month.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
@ -285,9 +285,16 @@ border-image: url(:/images/closepressed.png)
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="checkButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Forces the re-check of all shared directories. While automatic file checking only cares for new/removed files for efficiency reasons, this button will force the re-scan of all files, possibly re-hashing existing files that may have changed. </p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>check files</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/svg/refresh.svg</normaloff>:/icons/svg/refresh.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -311,8 +318,8 @@ border-image: url(:/images/closepressed.png)
|
|||
<string>Download</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/images/download16.png</normaloff>:/images/download16.png</iconset>
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/download.png</normaloff>:/icons/png/download.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -392,8 +399,8 @@ border-image: url(:/images/closepressed.png)
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -27,8 +27,6 @@ TransferUserNotify::TransferUserNotify(QObject *parent) :
|
|||
UserNotify(parent)
|
||||
{
|
||||
newTransferCount = 0;
|
||||
|
||||
// connect(NotifyQt::getInstance(), SIGNAL(downloadCompleteCountChanged(int)), this, SLOT(downloadCountChanged(int)));
|
||||
}
|
||||
|
||||
bool TransferUserNotify::hasSetting(QString *name, QString *group)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -173,6 +173,7 @@ signals:
|
|||
void playFiles(QStringList files);
|
||||
|
||||
private:
|
||||
void openFolder(const FileInfo& info);
|
||||
|
||||
RsDownloadListModel *DLListModel;
|
||||
QSortFilterProxyModel *DLLFilterModel;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue