mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-04-19 14:55:54 -04:00
fixed conflict
This commit is contained in:
commit
f959218a24
@ -1,15 +1,13 @@
|
||||
Compile Retroshare for Android
|
||||
==============================
|
||||
|
||||
== Introduction
|
||||
|
||||
Compiling an application for Android is not as easy as one would imagine,
|
||||
expecially one like RetroShare that has a big codebase and is not well
|
||||
documented.
|
||||
This document is aimed to empower the reader so she can hopefully succed or at
|
||||
least have a significant help in compiling her own RetroShare APK package
|
||||
documented. This document is aimed to empower the reader so she can hopefully
|
||||
succed or at least have a significant help in compiling her own RetroShare APK
|
||||
installable on Android.
|
||||
|
||||
|
||||
== Preparing The Environement
|
||||
|
||||
First of all setup your Qt for Android development environement following the
|
||||
@ -21,7 +19,7 @@ on your Android phone Qt for Android examples.
|
||||
But RetroShare is not as simple to compile as those examples. The good news is
|
||||
that Android NDK ships all the necessary to build a custom toolchain that is
|
||||
suitable to build RetroShare.
|
||||
In order to build the toolchain with needed library RetroShare provides the
|
||||
In order to build the toolchain with needed libraries RetroShare provides the
|
||||
+android-prepare-toolchain.sh+ script; before you execute it you should define
|
||||
some variables the script cannot determine in an easy and reliable manner by
|
||||
itself in your terminal.
|
||||
@ -33,7 +31,7 @@ export ANDROID_NDK_PATH="/opt/android-ndk/"
|
||||
|
||||
## The path where your fresh compiled toolchain will be installed, make sure
|
||||
## the parent exists
|
||||
export NDK_TOOLCHAIN_PATH="/home/$(whoami)/Development/android-toolchains/retroshare-android/"
|
||||
export NDK_TOOLCHAIN_PATH="${HOME}/Builds/android-toolchains/retroshare-android/"
|
||||
|
||||
## The CPU architecture of the Android device you want to target
|
||||
export ANDROID_NDK_ARCH="arm"
|
||||
|
@ -5,7 +5,7 @@
|
||||
[ -z ${ANDROID_NDK_ARCH+x} ] && export ANDROID_NDK_ARCH="arm"
|
||||
[ -z ${ANDROID_NDK_ABI_VER+x} ] && export ANDROID_NDK_ABI_VER="4.9"
|
||||
[ -z ${ANDROID_PLATFORM_VER+x} ] && export ANDROID_PLATFORM_VER="18"
|
||||
[ -z ${NDK_TOOLCHAIN_PATH+x} ] && export NDK_TOOLCHAIN_PATH="/home/$(whoami)/Development/android-toolchains/retroshare-android-${ANDROID_PLATFORM_VER}-${ANDROID_NDK_ARCH}-abi${ANDROID_NDK_ABI_VER}/"
|
||||
[ -z ${NDK_TOOLCHAIN_PATH+x} ] && export NDK_TOOLCHAIN_PATH="${HOME}/Builds/android-toolchains/retroshare-android-${ANDROID_PLATFORM_VER}-${ANDROID_NDK_ARCH}-abi${ANDROID_NDK_ABI_VER}/"
|
||||
[ -z ${HOST_NUM_CPU+x} ] && export HOST_NUM_CPU=4
|
||||
|
||||
runDir="$(pwd)"
|
||||
|
@ -1,5 +1,46 @@
|
||||
retroshare (0.6.3-1.XXXXXX~YYYYYY) YYYYYY; urgency=low
|
||||
|
||||
d61a5cd csoler Mon, 2 Oct 2017 22:23:26 +0200 attempt at fixing the re-hash bug. Now only using canonicalized filenames in hash cache
|
||||
22942dc csoler Sun, 1 Oct 2017 20:20:26 +0200 fixed bug causing suffix/prefix lists to contain an empty string
|
||||
bc05aaa csoler Sat, 30 Sep 2017 18:58:31 +0200 switched tokenQueue speed to 10 calls/sec, thus improving loading speeds. Still need to test for CPU load
|
||||
65977c0 csoler Sat, 30 Sep 2017 18:29:29 +0200 Merge pull request #1054 from PhenomRetroShare/Fix_GccWarningd
|
||||
06ebaa5 csoler Sat, 30 Sep 2017 18:28:24 +0200 Merge pull request #1055 from felisucoibi/master
|
||||
06063c5 felisu Sat, 30 Sep 2017 11:34:18 +0200 removed extra space
|
||||
b84c898 felisu Sat, 30 Sep 2017 00:29:07 +0200 Removed ... from text
|
||||
ef6fd38 felisu Thu, 28 Sep 2017 22:42:30 +0200 Changed prefixes and sifixes for startign with and ending with to be understandable.
|
||||
7f851f6 Phenom Thu, 28 Sep 2017 19:24:26 +0200 Fix Gcc Warning in p3banlist
|
||||
e66c0d1 csoler Wed, 27 Sep 2017 22:26:14 +0200 removed updateTotals() method. Replaced it with costless on-the-fly update of totals
|
||||
a00d2c9 csoler Tue, 26 Sep 2017 21:12:17 +0200 changed lobby to char room in chat system msgs
|
||||
8eae374 csoler Mon, 25 Sep 2017 22:14:34 +0200 Merge pull request #1053 from csoler/v0.6-FT
|
||||
0d9b6e7 csoler Mon, 25 Sep 2017 22:09:35 +0200 fixd broken layout
|
||||
cbeefda csoler Mon, 25 Sep 2017 21:35:59 +0200 Merge pull request #744 from RetroPooh/tunnel-names
|
||||
f98f16f Pooh Mon, 25 Sep 2017 22:31:49 +0300 Update TransfersDialog.cpp
|
||||
5970ff2 csoler Mon, 25 Sep 2017 21:14:30 +0200 Merge pull request #1052 from csoler/v0.6-FT
|
||||
40cda11 csoler Mon, 25 Sep 2017 21:05:42 +0200 removed delay when calling forceUpdate() on directories
|
||||
b969f31 csoler Mon, 25 Sep 2017 20:59:32 +0200 Merge pull request #1050 from csoler/v0.6-FT
|
||||
d8cb3fe csoler Mon, 25 Sep 2017 20:56:35 +0200 fixed not rehashing files that already exist in a different directory pointed by a symlink
|
||||
72dc1c7 Pooh Mon, 25 Sep 2017 21:50:12 +0300 Update TransfersDialog.cpp
|
||||
c47e6f6 Pooh Mon, 25 Sep 2017 21:43:41 +0300 Merge branch 'master' into tunnel-names
|
||||
4766a89 csoler Sun, 24 Sep 2017 23:51:47 +0200 added an additional hard limit to directory depth, just in case
|
||||
f497905 csoler Sun, 24 Sep 2017 23:43:52 +0200 fixed limitation of directory depth when indexing files
|
||||
abd7e25 csoler Sun, 24 Sep 2017 18:14:45 +0200 added checks for mMaxShareDepth and mIgnoreDuplicates
|
||||
2a99df4 csoler Sun, 24 Sep 2017 17:53:06 +0200 added UI and parameters for two new options in shared files: max share depth and ignore duplicates
|
||||
932eb49 csoler Sat, 23 Sep 2017 13:49:53 +0200 Merge pull request #1049 from Steve-V/minor-spelling-fix
|
||||
82c9c95 Steve- Fri, 22 Sep 2017 19:58:13 -0500 spelling fix ommitted -> omitted
|
||||
73cbf6c csoler Thu, 21 Sep 2017 23:47:11 +0200 Merge pull request #1047 from csoler/v0.6-FT
|
||||
a2ccf97 csoler Wed, 20 Sep 2017 22:57:32 +0200 removed the 4M files limit on 64bits systems
|
||||
308f8ca defnax Tue, 19 Sep 2017 18:34:58 +0200 update qrc file
|
||||
58ccf0b csoler Mon, 18 Sep 2017 22:50:35 +0200 Merge pull request #1045 from csoler/v0.6-FT
|
||||
bc2c9d5 csoler Mon, 18 Sep 2017 22:49:51 +0200 adding pending transfers 100 at a time instead of 1 at a time when loading
|
||||
52ca6d0 defnax Mon, 18 Sep 2017 20:49:40 +0200 Added Crystall Ball to emote file
|
||||
bf7d346 csoler Sun, 17 Sep 2017 20:27:44 +0200 Merge pull request #1043 from csoler/v0.6-FT
|
||||
e21dec4 csoler Sun, 17 Sep 2017 20:26:46 +0200 Merge pull request #1038 from PhenomRetroShare/Add_UploadUserColumn
|
||||
d8f621e csoler Sun, 17 Sep 2017 20:14:45 +0200 make forceDirectoryCheck() to desactivate the pause, in case it was left activated
|
||||
|
||||
-- Retroshare Dev Team <contact@retroshare.net> Sat, 14 Oct 2017 15:00:00 +0100
|
||||
|
||||
retroshare (0.6.3-1.20170917.c2f321d7~trusty) trusty; urgency=low
|
||||
|
||||
46d26bf csoler Tue, 12 Sep 2017 21:05:59 +0200 updated ubuntu packagign script
|
||||
f3c627d csoler Sat, 16 Sep 2017 22:13:53 +0200 Merge pull request #1042 from csoler/v0.6-FT
|
||||
8189d66 csoler Sat, 16 Sep 2017 22:13:15 +0200 fixed bug causing anon FT to not resume when restarting RS when the server enforces encryption
|
||||
|
46
build_scripts/Debian+Ubuntu/control.artful
Normal file
46
build_scripts/Debian+Ubuntu/control.artful
Normal file
@ -0,0 +1,46 @@
|
||||
Source: retroshare
|
||||
Section: devel
|
||||
Priority: standard
|
||||
Maintainer: Cyril Soler <csoler@users.sourceforge.net>
|
||||
Build-Depends: debhelper (>= 7), libglib2.0-dev, libupnp-dev, libssl-dev, libxss-dev, libgnome-keyring-dev, libbz2-dev, libspeex-dev, libspeexdsp-dev, libxslt1-dev, cmake, libcurl4-openssl-dev, libopencv-dev, tcl8.6, libsqlcipher-dev, libmicrohttpd-dev, libavcodec-dev, qtmultimedia5-dev, qttools5-dev, libqt5x11extras5-dev, qt5-default
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: http://retroshare.sourceforge.net
|
||||
|
||||
Package: retroshare-voip-plugin
|
||||
Architecture: any
|
||||
Conflicts: retroshare06-voip-plugin
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, retroshare, libspeex1, libspeexdsp1, libqt5multimedia5
|
||||
Description: RetroShare VOIP plugin
|
||||
This package provides a plugin for RetroShare, a secured Friend-to-Friend communication
|
||||
plateform. The plugin adds voice-over-IP functionality to the private chat window. Both
|
||||
friends chatting together need the plugin installed to be able to talk together.
|
||||
|
||||
Package: retroshare-feedreader-plugin
|
||||
Architecture: any
|
||||
Conflicts: retroshare06-feedreader-plugin
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, retroshare
|
||||
Description: RetroShare FeedReader plugin
|
||||
This package provides a plugin for RetroShare, a secured Friend-to-Friend communication
|
||||
plateform. The plugin adds a RSS feed reader tab to retroshare.
|
||||
|
||||
Package: retroshare-nogui
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, gnome-keyring
|
||||
Conflicts: retroshare,retroshare06-nogui
|
||||
Description: Secure communication with friends
|
||||
This is the command-line client for RetroShare network. This client
|
||||
can be contacted and talked-to using SSL. Clients exist for portable
|
||||
devices running e.g. Android.
|
||||
|
||||
Package: retroshare
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, gnome-keyring
|
||||
Conflicts: retroshare-nogui,retroshare06
|
||||
Description: Secure communication with friends
|
||||
RetroShare is a Open Source cross-platform, private and secure decentralised
|
||||
commmunication platform. It lets you to securely chat and share files with your
|
||||
friends and family, using a web-of-trust to authenticate peers and OpenSSL to
|
||||
encrypt all communication. RetroShare provides filesharing, chat, messages,
|
||||
forums and channels.
|
||||
|
||||
|
@ -55,7 +55,7 @@ while [ ${#} -gt 0 ]; do
|
||||
done
|
||||
|
||||
if test "${dist}" = "" ; then
|
||||
dist="precise trusty vivid xenial zesty"
|
||||
dist="precise trusty xenial zesty artful"
|
||||
fi
|
||||
|
||||
echo Attempting to get revision number...
|
||||
@ -121,23 +121,11 @@ for i in ${dist}; do
|
||||
echo copying changelog for ${i}
|
||||
sed -e s/XXXXXX/"${rev}"/g -e s/YYYYYY/"${i}"/g ../changelog > debian/changelog
|
||||
|
||||
if test "${i}" = "lucid" ; then
|
||||
cp ../control.ubuntu_lucid debian/control
|
||||
elif test "${i}" = "zesty" ; then
|
||||
cp ../control.zesty debian/control
|
||||
elif test "${i}" = "squeeze" ; then
|
||||
cp ../control.squeeze_bubba3 debian/control
|
||||
elif test "${i}" = "precise" ; then
|
||||
cp ../control.precise debian/control
|
||||
elif test "${i}" = "xenial" ; then
|
||||
cp ../control.xenial debian/control
|
||||
elif test "${i}" = "yakkety" ; then
|
||||
cp ../control.yakkety debian/control
|
||||
elif test "${i}" = "stretch" ; then
|
||||
cp ../control.${i} debian/control
|
||||
elif test "${i}" = "jessie" ; then
|
||||
cp ../control.${i} debian/control
|
||||
if test -f ../control."${i}" ; then
|
||||
echo \/\!\\ Using specific control file for distribution "${i}"
|
||||
cp ../control."${i}" debian/control
|
||||
else
|
||||
echo Using standard control file control."${i}" for distribution "${i}"
|
||||
cp ../debian/control debian/control
|
||||
fi
|
||||
|
||||
|
@ -31,32 +31,32 @@ CONTRIBUTE
|
||||
|
||||
TODO
|
||||
----
|
||||
[ ] make stylesheets or find reusable sass/css components
|
||||
- [ ] make stylesheets or find reusable sass/css components
|
||||
google material design has nice rules for color, spacing and everything: https://www.google.de/design/spec/material-design/introduction.html
|
||||
[ ] find icons, maybe use google material design iconfont
|
||||
[X] use urls/mithril routing for the menu. urls could replace state stored in rs.content
|
||||
[X] drag and drop private key upload and import
|
||||
[X] link from peer location to chat (use urls and mithril routing)
|
||||
[X] add/remove friend, own cert
|
||||
[X] downloads, search
|
||||
[ ] make reusable infinite list controller, the js part to load data from Pagination.h (tweak Pagination.h to make everything work)
|
||||
- [ ] find icons, maybe use google material design iconfont
|
||||
- [X] use urls/mithril routing for the menu. urls could replace state stored in rs.content
|
||||
- [X] drag and drop private key upload and import
|
||||
- [X] link from peer location to chat (use urls and mithril routing)
|
||||
- [X] add/remove friend, own cert
|
||||
- [X] downloads, search
|
||||
- [ ] make reusable infinite list controller, the js part to load data from Pagination.h (tweak Pagination.h to make everything work)
|
||||
should provide forward, backward and follow-list-end
|
||||
[ ] backend: view/create identities
|
||||
[ ] backend: chat lobby participants list
|
||||
[X] chat: send_message
|
||||
[ ] backend: chat typing notifications
|
||||
[ ] make routines to handle retroshare links
|
||||
[ ] backend: edit shared folders
|
||||
[ ] backend: view shared files
|
||||
[ ] redirect if a url is not usable in the current runstate (e.g. redirect from login page to home page, after login)
|
||||
[X] sort friendslist
|
||||
- [ ] backend: view/create identities
|
||||
- [ ] backend: chat lobby participants list
|
||||
- [X] chat: send_message
|
||||
- [ ] backend: chat typing notifications
|
||||
- [ ] make routines to handle retroshare links
|
||||
- [ ] backend: edit shared folders
|
||||
- [ ] backend: view shared files
|
||||
- [ ] redirect if a url is not usable in the current runstate (e.g. redirect from login page to home page, after login)
|
||||
- [X] sort friendslist
|
||||
|
||||
need 4 master
|
||||
-------------
|
||||
[X] unsubscribe lobby
|
||||
[X] unread chat message counter in menu
|
||||
[X] list chat-lobby participants
|
||||
[X] creating app.js on build (no need for npm on regulary build)
|
||||
- [X] unsubscribe lobby
|
||||
- [X] unread chat message counter in menu
|
||||
- [X] list chat-lobby participants
|
||||
- [X] creating app.js on build (no need for npm on regulary build)
|
||||
|
||||
url-handling (brainstorming)
|
||||
----------------------------
|
||||
|
@ -35,6 +35,8 @@
|
||||
|
||||
//#define DEBUG_DIRECTORY_STORAGE 1
|
||||
|
||||
typedef FileListIO::read_error read_error;
|
||||
|
||||
/******************************************************************************************************************/
|
||||
/* Internal File Hierarchy Storage */
|
||||
/******************************************************************************************************************/
|
||||
@ -1041,22 +1043,6 @@ bool InternalFileHierarchyStorage::save(const std::string& fname)
|
||||
}
|
||||
}
|
||||
|
||||
class read_error
|
||||
{
|
||||
public:
|
||||
read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag)
|
||||
{
|
||||
std::ostringstream s ;
|
||||
s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl;
|
||||
err_string = s.str();
|
||||
}
|
||||
read_error(const std::string& s) : err_string(s) {}
|
||||
|
||||
const std::string& what() const { return err_string ; }
|
||||
private:
|
||||
std::string err_string ;
|
||||
};
|
||||
|
||||
bool InternalFileHierarchyStorage::load(const std::string& fname)
|
||||
{
|
||||
unsigned char *buffer = NULL ;
|
||||
|
298
libretroshare/src/file_sharing/file_tree.cc
Normal file
298
libretroshare/src/file_sharing/file_tree.cc
Normal file
@ -0,0 +1,298 @@
|
||||
#include <iomanip>
|
||||
#include <util/radix64.h>
|
||||
#include <util/rsdir.h>
|
||||
|
||||
#include "file_sharing_defaults.h"
|
||||
#include "filelist_io.h"
|
||||
#include "file_tree.h"
|
||||
|
||||
std::string FileTreeImpl::toRadix64() const
|
||||
{
|
||||
unsigned char *buff = NULL ;
|
||||
uint32_t size = 0 ;
|
||||
|
||||
serialise(buff,size) ;
|
||||
|
||||
std::string res ;
|
||||
|
||||
Radix64::encode(buff,size,res) ;
|
||||
|
||||
free(buff) ;
|
||||
return res ;
|
||||
}
|
||||
|
||||
FileTree *FileTree::create(const std::string& radix64_string)
|
||||
{
|
||||
FileTreeImpl *ft = new FileTreeImpl ;
|
||||
|
||||
std::vector<uint8_t> mem = Radix64::decode(radix64_string);
|
||||
ft->deserialise(mem.data(),mem.size()) ;
|
||||
|
||||
return ft ;
|
||||
}
|
||||
|
||||
void FileTreeImpl::recurs_buildFileTree(FileTreeImpl& ft,uint32_t index,const DirDetails& dd,bool remote,bool remove_top_dirs)
|
||||
{
|
||||
if(ft.mDirs.size() <= index)
|
||||
ft.mDirs.resize(index+1) ;
|
||||
|
||||
if(remove_top_dirs)
|
||||
ft.mDirs[index].name = RsDirUtil::getTopDir(dd.name) ;
|
||||
else
|
||||
ft.mDirs[index].name = dd.name ;
|
||||
|
||||
ft.mDirs[index].subfiles.clear();
|
||||
ft.mDirs[index].subdirs.clear();
|
||||
|
||||
DirDetails dd2 ;
|
||||
|
||||
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
|
||||
|
||||
for(uint32_t i=0;i<dd.children.size();++i)
|
||||
if(rsFiles->RequestDirDetails(dd.children[i].ref,dd2,flags))
|
||||
{
|
||||
if(dd.children[i].type == DIR_TYPE_FILE)
|
||||
{
|
||||
FileTree::FileData f ;
|
||||
f.name = dd2.name ;
|
||||
f.size = dd2.count ;
|
||||
f.hash = dd2.hash ;
|
||||
|
||||
ft.mDirs[index].subfiles.push_back(ft.mFiles.size()) ;
|
||||
ft.mFiles.push_back(f) ;
|
||||
|
||||
ft.mTotalFiles++ ;
|
||||
ft.mTotalSize += f.size ;
|
||||
}
|
||||
else if(dd.children[i].type == DIR_TYPE_DIR)
|
||||
{
|
||||
ft.mDirs[index].subdirs.push_back(ft.mDirs.size());
|
||||
recurs_buildFileTree(ft,ft.mDirs.size(),dd2,remote,remove_top_dirs) ;
|
||||
}
|
||||
else
|
||||
std::cerr << "(EE) Unsupported DirDetails type." << std::endl;
|
||||
}
|
||||
else
|
||||
std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl;
|
||||
}
|
||||
|
||||
bool FileTreeImpl::getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const
|
||||
{
|
||||
if(index >= mDirs.size())
|
||||
return false ;
|
||||
|
||||
name = mDirs[index].name;
|
||||
subdirs = mDirs[index].subdirs ;
|
||||
|
||||
subfiles.clear() ;
|
||||
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
|
||||
subfiles.push_back(mFiles[mDirs[index].subfiles[i]]);
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
FileTree *FileTree::create(const DirDetails& dd, bool remote,bool remove_top_dirs)
|
||||
{
|
||||
FileTreeImpl *ft = new FileTreeImpl ;
|
||||
|
||||
FileTreeImpl::recurs_buildFileTree(*ft,0,dd,remote,remove_top_dirs) ;
|
||||
|
||||
return ft ;
|
||||
}
|
||||
|
||||
typedef FileListIO::read_error read_error ;
|
||||
|
||||
bool FileTreeImpl::deserialise(unsigned char *buffer,uint32_t buffer_size)
|
||||
{
|
||||
uint32_t buffer_offset = 0 ;
|
||||
|
||||
mTotalFiles = 0;
|
||||
mTotalSize = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// Read some header
|
||||
|
||||
uint32_t version,n_dirs,n_files ;
|
||||
|
||||
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,version)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION) ;
|
||||
if(version != (uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001) throw std::runtime_error("Wrong version number") ;
|
||||
|
||||
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_files)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_dirs)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
|
||||
// Write all file/dir entries
|
||||
|
||||
mFiles.resize(n_files) ;
|
||||
mDirs.resize(n_dirs) ;
|
||||
|
||||
unsigned char *node_section_data = NULL ;
|
||||
uint32_t node_section_size = 0 ;
|
||||
|
||||
for(uint32_t i=0;i<mFiles.size() && buffer_offset < buffer_size;++i) // only the 2nd condition really is needed. The first one ensures that the loop wont go forever.
|
||||
{
|
||||
uint32_t node_section_offset = 0 ;
|
||||
#ifdef DEBUG_DIRECTORY_STORAGE
|
||||
std::cerr << "reading node " << i << ", offset " << buffer_offset << " : " << RsUtil::BinToHex(&buffer[buffer_offset],std::min((int)buffer_size - (int)buffer_offset,100)) << "..." << std::endl;
|
||||
#endif
|
||||
|
||||
if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,node_section_data,node_section_size))
|
||||
{
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,mFiles[i].name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ;
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,mFiles[i].size )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ) ;
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,mFiles[i].hash )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH) ;
|
||||
|
||||
mTotalFiles++ ;
|
||||
mTotalSize += mFiles[i].size ;
|
||||
}
|
||||
else
|
||||
throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY) ;
|
||||
}
|
||||
|
||||
for(uint32_t i=0;i<mDirs.size() && buffer_offset < buffer_size;++i)
|
||||
{
|
||||
uint32_t node_section_offset = 0 ;
|
||||
|
||||
if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,node_section_data,node_section_size))
|
||||
{
|
||||
DirData& de(mDirs[i]) ;
|
||||
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME,de.name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ;
|
||||
|
||||
uint32_t n_subdirs = 0 ;
|
||||
uint32_t n_subfiles = 0 ;
|
||||
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
|
||||
for(uint32_t j=0;j<n_subdirs;++j)
|
||||
{
|
||||
uint32_t di = 0 ;
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,di)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
de.subdirs.push_back(di) ;
|
||||
}
|
||||
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
|
||||
for(uint32_t j=0;j<n_subfiles;++j)
|
||||
{
|
||||
uint32_t fi = 0 ;
|
||||
if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,fi)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ;
|
||||
de.subfiles.push_back(fi) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY) ;
|
||||
}
|
||||
free(node_section_data) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
catch(read_error& e)
|
||||
{
|
||||
#ifdef DEBUG_DIRECTORY_STORAGE
|
||||
std::cerr << "Error while reading: " << e.what() << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool FileTreeImpl::serialise(unsigned char *& buffer,uint32_t& buffer_size) const
|
||||
{
|
||||
buffer = 0 ;
|
||||
uint32_t buffer_offset = 0 ;
|
||||
|
||||
unsigned char *tmp_section_data = (unsigned char*)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ;
|
||||
|
||||
if(!tmp_section_data)
|
||||
return false;
|
||||
|
||||
uint32_t tmp_section_size = FL_BASE_TMP_SECTION_SIZE ;
|
||||
|
||||
try
|
||||
{
|
||||
// Write some header
|
||||
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,(uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001)) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mFiles.size())) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t) mDirs.size())) throw std::runtime_error("Write error") ;
|
||||
|
||||
// Write all file/dir entries
|
||||
|
||||
for(uint32_t i=0;i<mFiles.size();++i)
|
||||
{
|
||||
const FileData& fe(mFiles[i]) ;
|
||||
|
||||
uint32_t file_section_offset = 0 ;
|
||||
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,fe.name )) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,fe.size )) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,fe.hash )) throw std::runtime_error("Write error") ;
|
||||
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,tmp_section_data,file_section_offset)) throw std::runtime_error("Write error") ;
|
||||
}
|
||||
|
||||
for(uint32_t i=0;i<mDirs.size();++i)
|
||||
{
|
||||
const DirData& de(mDirs[i]) ;
|
||||
|
||||
uint32_t dir_section_offset = 0 ;
|
||||
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,de.name )) throw std::runtime_error("Write error") ;
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs.size())) throw std::runtime_error("Write error") ;
|
||||
|
||||
for(uint32_t j=0;j<de.subdirs.size();++j)
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs[j])) throw std::runtime_error("Write error") ;
|
||||
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subfiles.size())) throw std::runtime_error("Write error") ;
|
||||
|
||||
for(uint32_t j=0;j<de.subfiles.size();++j)
|
||||
if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subfiles[j])) throw std::runtime_error("Write error") ;
|
||||
|
||||
if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,tmp_section_data,dir_section_offset)) throw std::runtime_error("Write error") ;
|
||||
}
|
||||
|
||||
free(tmp_section_data) ;
|
||||
buffer_size = buffer_offset;
|
||||
|
||||
return true ;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << "Error while writing: " << e.what() << std::endl;
|
||||
|
||||
if(buffer != NULL)
|
||||
free(buffer) ;
|
||||
|
||||
if(tmp_section_data != NULL)
|
||||
free(tmp_section_data) ;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FileTreeImpl::print() const
|
||||
{
|
||||
std::cerr << "File hierarchy: name=" << mDirs[0].name << " size=" << mTotalSize << std::endl;
|
||||
recurs_print(0," ") ;
|
||||
}
|
||||
|
||||
void FileTreeImpl::recurs_print(uint32_t index,const std::string& indent) const
|
||||
{
|
||||
if(index >= mDirs.size())
|
||||
{
|
||||
std::cerr << "(EE) inconsistent FileTree structure" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cerr << indent << mDirs[index].name << std::endl;
|
||||
|
||||
for(uint32_t i=0;i<mDirs[index].subdirs.size();++i)
|
||||
recurs_print(mDirs[index].subdirs[i],indent+" ") ;
|
||||
|
||||
for(uint32_t i=0;i<mDirs[index].subfiles.size();++i)
|
||||
{
|
||||
const FileData& fd(mFiles[mDirs[index].subfiles[i]]) ;
|
||||
|
||||
std::cerr << indent << " " << fd.hash << " " << std::setprecision(8) << fd.size << " " << fd.name << std::endl;
|
||||
}
|
||||
}
|
33
libretroshare/src/file_sharing/file_tree.h
Normal file
33
libretroshare/src/file_sharing/file_tree.h
Normal file
@ -0,0 +1,33 @@
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
class FileTreeImpl: public FileTree
|
||||
{
|
||||
public:
|
||||
FileTreeImpl()
|
||||
{
|
||||
mTotalFiles = 0 ;
|
||||
mTotalSize = 0 ;
|
||||
}
|
||||
|
||||
virtual std::string toRadix64() const ;
|
||||
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const ;
|
||||
virtual void print() const ;
|
||||
|
||||
bool serialise(unsigned char *& data,uint32_t& data_size) const ;
|
||||
bool deserialise(unsigned char* data, uint32_t data_size) ;
|
||||
|
||||
protected:
|
||||
void recurs_print(uint32_t index,const std::string& indent) const;
|
||||
|
||||
static void recurs_buildFileTree(FileTreeImpl& ft, uint32_t index, const DirDetails& dd, bool remote, bool remove_top_dirs);
|
||||
|
||||
struct DirData {
|
||||
std::string name;
|
||||
std::vector<uint32_t> subdirs ;
|
||||
std::vector<uint32_t> subfiles ;
|
||||
};
|
||||
std::vector<FileData> mFiles ;
|
||||
std::vector<DirData> mDirs ;
|
||||
|
||||
friend class FileTree ;
|
||||
};
|
@ -22,12 +22,22 @@
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include "retroshare/rsids.h"
|
||||
#include "pqi/authssl.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsprint.h"
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
#include "filelist_io.h"
|
||||
|
||||
FileListIO::read_error::read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag)
|
||||
{
|
||||
std::ostringstream s ;
|
||||
s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl;
|
||||
err_string = s.str();
|
||||
}
|
||||
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint32_t & val) { return setRawUInt32(buff,size,&offset,val) ; }
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint64_t & val) { return setRawUInt64(buff,size,&offset,val) ; }
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const std::string & val) { return setRawString(buff,size,&offset,val) ; }
|
||||
|
@ -36,6 +36,7 @@
|
||||
// WARNING: the encoding is system-dependent, so this should *not* be used to exchange data between computers.
|
||||
|
||||
static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_STORAGE_VERSION_0001 = 0x00000001 ;
|
||||
static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 = 0x00010001 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_UNKNOWN = 0x00 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION = 0x01 ;
|
||||
@ -65,6 +66,7 @@ static const uint8_t FILE_LIST_IO_TAG_RAW_NUMBER = 0x62 ;
|
||||
|
||||
static const uint32_t SECTION_HEADER_MAX_SIZE = 6 ; // section tag (1 byte) + size (max = 5 bytes)
|
||||
|
||||
|
||||
class FileListIO
|
||||
{
|
||||
public:
|
||||
@ -93,7 +95,19 @@ public:
|
||||
return deserialise(buff,buff_size,offset,val);
|
||||
}
|
||||
|
||||
static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ;
|
||||
class read_error
|
||||
{
|
||||
public:
|
||||
read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag);
|
||||
read_error(const std::string& s) : err_string(s) {}
|
||||
|
||||
const std::string& what() const { return err_string ; }
|
||||
private:
|
||||
std::string err_string ;
|
||||
};
|
||||
|
||||
|
||||
static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ;
|
||||
static bool readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) ;
|
||||
|
||||
template<class T> static bool serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const T& val) ;
|
||||
|
@ -47,6 +47,7 @@ file_lists {
|
||||
file_sharing/directory_updater.h \
|
||||
file_sharing/rsfilelistitems.h \
|
||||
file_sharing/dir_hierarchy.h \
|
||||
file_sharing/file_tree.h \
|
||||
file_sharing/file_sharing_defaults.h
|
||||
|
||||
SOURCES *= file_sharing/p3filelists.cc \
|
||||
@ -55,6 +56,7 @@ file_lists {
|
||||
file_sharing/directory_storage.cc \
|
||||
file_sharing/directory_updater.cc \
|
||||
file_sharing/dir_hierarchy.cc \
|
||||
file_sharing/file_tree.cc \
|
||||
file_sharing/rsfilelistitems.cc
|
||||
}
|
||||
|
||||
@ -916,7 +918,7 @@ test_bitdht {
|
||||
################################# Android #####################################
|
||||
|
||||
android-g++ {
|
||||
## ifaddrs is missing on Android add them don't use the one from
|
||||
## ifaddrs is missing on Android to add them don't use the one from
|
||||
## https://github.com/morristech/android-ifaddrs
|
||||
## because they crash, use QNetworkInterface from Qt instead
|
||||
CONFIG *= qt
|
||||
|
@ -134,6 +134,38 @@ struct SharedDirStats
|
||||
uint64_t total_shared_size ;
|
||||
};
|
||||
|
||||
// This class represents a tree of directories and files, only with their names size and hash. It is used to create collection links in the GUI
|
||||
// and to transmit directory information between services. This class is independent from the existing FileHierarchy classes used in storage because
|
||||
// we need a very copact serialization and storage size since we create links with it. Besides, we cannot afford to risk the leak of other local information
|
||||
// by using the orignal classes.
|
||||
|
||||
class FileTree
|
||||
{
|
||||
public:
|
||||
virtual ~FileTree() {}
|
||||
|
||||
static FileTree *create(const DirDetails& dd, bool remote, bool remove_top_dirs = true) ;
|
||||
static FileTree *create(const std::string& radix64_string) ;
|
||||
|
||||
virtual std::string toRadix64() const =0 ;
|
||||
|
||||
// These methods allow the user to browse the hierarchy
|
||||
|
||||
struct FileData {
|
||||
std::string name ;
|
||||
uint64_t size ;
|
||||
RsFileHash hash ;
|
||||
};
|
||||
|
||||
virtual uint32_t root() const { return 0;}
|
||||
virtual bool getDirectoryContent(uint32_t index,std::string& name,std::vector<uint32_t>& subdirs,std::vector<FileData>& subfiles) const = 0;
|
||||
|
||||
virtual void print() const=0;
|
||||
|
||||
uint32_t mTotalFiles ;
|
||||
uint64_t mTotalSize ;
|
||||
};
|
||||
|
||||
class RsFiles
|
||||
{
|
||||
public:
|
||||
|
@ -803,7 +803,8 @@ static bool checkAccount(std::string accountdir, AccountDetails &account,std::ma
|
||||
|
||||
/* Use RetroShare's exe dir */
|
||||
dataDirectory = ".";
|
||||
|
||||
#elif defined(ANDROID)
|
||||
dataDirectory = defaultBaseDirectory()+"/usr/share/retroshare";
|
||||
#elif defined(DATA_DIR)
|
||||
dataDirectory = DATA_DIR;
|
||||
// For all other OS the data directory must be set in libretroshare.pro
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "retroshare-gui/RsAutoUpdatePage.h"
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
#include "gui/common/RsCollectionFile.h"
|
||||
#include "gui/common/RsCollection.h"
|
||||
#include "gui/common/FilesDefs.h"
|
||||
#include "gui/common/RsUrlHandler.h"
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
@ -345,7 +345,7 @@ void SearchDialog::searchResultWidgetCustomPopupMenu( QPoint /*point*/ )
|
||||
QList<QTreeWidgetItem*> item =ui.searchResultWidget->selectedItems() ;
|
||||
if (item.at(0)->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool()) {
|
||||
contextMnu.addAction(QIcon(IMAGE_OPENFOLDER), tr("Open Folder"), this, SLOT(openFolderSearch())) ;
|
||||
if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollectionFile::ExtensionString)) {
|
||||
if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollection::ExtensionString)) {
|
||||
add_CollActions = true ;
|
||||
}//if (item.at(0)->text(SR_NAME_COL).endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (item.at(0)->data(SR_DATA_COL, SR_ROLE_LOCAL).toBool())
|
||||
@ -448,7 +448,7 @@ void SearchDialog::collCreate()
|
||||
}//if (!item->text(SR_HASH_COL).isEmpty())
|
||||
}//for (int i = 0; i < numdls; ++i)
|
||||
|
||||
RsCollectionFile(dirVec).openNewColl(this);
|
||||
RsCollection(dirVec).openNewColl(this);
|
||||
}
|
||||
|
||||
void SearchDialog::collModif()
|
||||
@ -476,8 +476,8 @@ void SearchDialog::collModif()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
@ -508,8 +508,8 @@ void SearchDialog::collView()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath(), true);
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
@ -540,8 +540,8 @@ void SearchDialog::collOpen()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
if (collection.load(qinfo.absoluteFilePath())) {
|
||||
collection.downloadFiles();
|
||||
return;
|
||||
@ -552,7 +552,7 @@ void SearchDialog::collOpen()
|
||||
}
|
||||
}
|
||||
|
||||
RsCollectionFile collection;
|
||||
RsCollection collection;
|
||||
if (collection.load(this)) {
|
||||
collection.downloadFiles();
|
||||
}//if (collection.load(this))
|
||||
|
@ -33,13 +33,15 @@
|
||||
|
||||
#include "SharedFilesDialog.h"
|
||||
#include "gui/notifyqt.h"
|
||||
#include "gui/MainWindow.h"
|
||||
#include "gui/RemoteDirModel.h"
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "gui/ShareManager.h"
|
||||
#include "gui/common/PeerDefs.h"
|
||||
#include "gui/common/RsCollectionFile.h"
|
||||
#include "gui/common/RsCollection.h"
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
#include "gui/settings/AddFileAssociationDialog.h"
|
||||
#include "gui/gxschannels/GxsChannelDialog.h"
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "util/RsAction.h"
|
||||
@ -61,6 +63,7 @@
|
||||
#define IMAGE_OPENFOLDER ":/images/folderopen.png"
|
||||
#define IMAGE_OPENFILE ":/images/fileopen.png"
|
||||
#define IMAGE_LIBRARY ":/images/library.png"
|
||||
#define IMAGE_CHANNEL ":/images/channels32.png"
|
||||
#define IMAGE_COLLCREATE ":/images/library_add.png"
|
||||
#define IMAGE_COLLMODIF ":/images/library_edit.png"
|
||||
#define IMAGE_COLLVIEW ":/images/library_view.png"
|
||||
@ -154,9 +157,6 @@ SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareD
|
||||
connect(notify, SIGNAL(filesPreModChanged(bool)), this, SLOT(preModDirectories(bool)));
|
||||
connect(notify, SIGNAL(filesPostModChanged(bool)), this, SLOT(postModDirectories(bool)));
|
||||
|
||||
//== connect(ui.localButton, SIGNAL(toggled(bool)), this, SLOT(showFrame(bool)));
|
||||
//== connect(ui.remoteButton, SIGNAL(toggled(bool)), this, SLOT(showFrameRemote(bool)));
|
||||
//== connect(ui.splittedButton, SIGNAL(toggled(bool)), this, SLOT(showFrameSplitted(bool)));
|
||||
connect(ui.viewType_CB, SIGNAL(currentIndexChanged(int)), this, SLOT(changeCurrentViewModel(int)));
|
||||
|
||||
connect( ui.dirTreeView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( spawnCustomPopupMenu( QPoint ) ) );
|
||||
@ -499,36 +499,24 @@ void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
||||
|
||||
QMenu contextMnu( this ) ;
|
||||
|
||||
//bool bIsRsColl = currentFile.endsWith(RsCollectionFile::ExtensionString);
|
||||
collCreateAct->setEnabled(true);
|
||||
//collModifAct->setEnabled(bIsRsColl);
|
||||
//collViewAct->setEnabled(bIsRsColl);
|
||||
collOpenAct->setEnabled(true);
|
||||
|
||||
QMenu collectionMenu(tr("Collection"), this);
|
||||
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
|
||||
collectionMenu.addAction(collCreateAct);
|
||||
//collectionMenu.addAction(collModifAct);
|
||||
//collectionMenu.addAction(collViewAct);
|
||||
collectionMenu.addAction(collOpenAct);
|
||||
|
||||
QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), &contextMnu ) ;
|
||||
connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ;
|
||||
contextMnu.addAction( downloadAct) ;
|
||||
|
||||
if ( type == DIR_TYPE_FILE ) {
|
||||
//QAction *copyremotelinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Link" ), &contextMnu ) ;
|
||||
//connect( copyremotelinkAct , SIGNAL( triggered() ), this, SLOT( copyLink() ) ) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addAction( copylinkAct) ;
|
||||
contextMnu.addAction( sendlinkAct) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
|
||||
|
||||
//QAction *sendremotelinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Link" ), &contextMnu ) ;
|
||||
//connect( sendremotelinkAct , SIGNAL( triggered() ), this, SLOT( sendremoteLinkTo( ) ) ) ;
|
||||
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addAction( copylinkAct) ;
|
||||
contextMnu.addAction( sendlinkAct) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(recommendFilesToMsg())) ;
|
||||
}//if (type == DIR_TYPE_FILE)
|
||||
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addMenu(&collectionMenu) ;
|
||||
@ -542,7 +530,7 @@ QModelIndexList SharedFilesDialog::getSelected()
|
||||
QModelIndexList proxyList ;
|
||||
for (QModelIndexList::iterator index = list.begin(); index != list.end(); ++index ) {
|
||||
proxyList.append(proxyModel->mapToSource(*index)) ;
|
||||
}//for (QModelIndexList::iterator index
|
||||
}
|
||||
|
||||
return proxyList ;
|
||||
}
|
||||
@ -567,62 +555,59 @@ void RemoteSharedFilesDialog::downloadRemoteSelected()
|
||||
model -> downloadSelected(lst) ;
|
||||
}
|
||||
|
||||
void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
|
||||
void SharedFilesDialog::copyLinks(const QModelIndexList& lst, bool remote,QList<RetroShareLink>& urls,bool& has_unhashed_files)
|
||||
{
|
||||
std::vector<DirDetails> dirVec;
|
||||
std::vector<DirDetails> dirVec;
|
||||
|
||||
model->getDirDetailsFromSelect(lst, dirVec);
|
||||
model->getDirDetailsFromSelect(lst, dirVec);
|
||||
|
||||
QList<RetroShareLink> urls ;
|
||||
has_unhashed_files = false;
|
||||
|
||||
bool has_unhashed_files = false;
|
||||
for (int i = 0, n = dirVec.size(); i < n; ++i)
|
||||
{
|
||||
const DirDetails& details = dirVec[i];
|
||||
|
||||
for (int i = 0, n = dirVec.size(); i < n; ++i)
|
||||
{
|
||||
const DirDetails& details = dirVec[i];
|
||||
if (details.type == DIR_TYPE_DIR)
|
||||
{
|
||||
FileTree *ft = FileTree::create(details,remote) ;
|
||||
|
||||
if (details.type == DIR_TYPE_DIR)
|
||||
{
|
||||
for(uint32_t j=0;j<details.children.size();++j)
|
||||
{
|
||||
const DirStub& dirStub = details.children[j];
|
||||
std::cerr << "Created collection file tree:" << std::endl;
|
||||
ft->print();
|
||||
|
||||
DirDetails details;
|
||||
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
|
||||
QString dir_name = QDir(QString::fromUtf8(details.name.c_str())).dirName();
|
||||
|
||||
// do not recursive copy sub dirs.
|
||||
if (!rsFiles->RequestDirDetails(dirStub.ref, details, flags) || details.type != DIR_TYPE_FILE)
|
||||
continue;
|
||||
RetroShareLink link = RetroShareLink::createCollection(dir_name,ft->mTotalSize,ft->mTotalFiles,QString::fromStdString(ft->toRadix64())) ;
|
||||
|
||||
if(details.hash.isNull())
|
||||
{
|
||||
has_unhashed_files = true;
|
||||
continue;
|
||||
}
|
||||
if(link.valid())
|
||||
urls.push_back(link) ;
|
||||
|
||||
RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.toStdString().c_str());
|
||||
if (link.valid()) {
|
||||
urls.push_back(link) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(details.hash.isNull())
|
||||
delete ft ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(details.hash.isNull())
|
||||
{
|
||||
has_unhashed_files = true;
|
||||
continue;
|
||||
}
|
||||
RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.toStdString().c_str());
|
||||
if (link.valid()) {
|
||||
urls.push_back(link) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.toStdString().c_str());
|
||||
if (link.valid()) {
|
||||
urls.push_back(link) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
|
||||
{
|
||||
QList<RetroShareLink> urls ;
|
||||
bool has_unhashed_files = false;
|
||||
|
||||
copyLinks(lst,remote,urls,has_unhashed_files) ;
|
||||
RSLinkClipboard::copyLinks(urls) ;
|
||||
|
||||
if(has_unhashed_files)
|
||||
QMessageBox::warning(NULL,tr("Some files have been omitted"),tr("Some files have been omitted because their hash is not available yet.")) ;
|
||||
QMessageBox::warning(NULL,tr("Some files have been omitted"),tr("Some files have been omitted because they have not been indexed yet.")) ;
|
||||
}
|
||||
|
||||
void SharedFilesDialog::copyLink()
|
||||
@ -692,11 +677,11 @@ void SharedFilesDialog::collModif()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedFilesDialog::collView()
|
||||
@ -722,11 +707,11 @@ void SharedFilesDialog::collView()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath(), true);
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SharedFilesDialog::collOpen()
|
||||
@ -752,8 +737,8 @@ void SharedFilesDialog::collOpen()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
if (collection.load(qinfo.absoluteFilePath())) {
|
||||
collection.downloadFiles();
|
||||
return;
|
||||
@ -763,10 +748,10 @@ void SharedFilesDialog::collOpen()
|
||||
}
|
||||
}
|
||||
|
||||
RsCollectionFile collection;
|
||||
RsCollection collection;
|
||||
if (collection.load(this)) {
|
||||
collection.downloadFiles();
|
||||
}//if (collection.load(this))
|
||||
}
|
||||
}
|
||||
|
||||
void LocalSharedFilesDialog::playselectedfiles()
|
||||
@ -995,7 +980,7 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
||||
|
||||
QMenu contextMnu(this) ;
|
||||
|
||||
bool bIsRsColl = currentFile.endsWith(RsCollectionFile::ExtensionString);
|
||||
bool bIsRsColl = currentFile.endsWith(RsCollection::ExtensionString);
|
||||
collCreateAct->setEnabled(true);
|
||||
collModifAct->setEnabled(bIsRsColl);
|
||||
collViewAct->setEnabled(bIsRsColl);
|
||||
@ -1011,6 +996,7 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
||||
switch (type) {
|
||||
case DIR_TYPE_DIR :
|
||||
contextMnu.addAction(openfolderAct) ;
|
||||
contextMnu.addAction(copylinkAct) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addMenu(&collectionMenu) ;
|
||||
break ;
|
||||
@ -1023,14 +1009,51 @@ void LocalSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addMenu(&collectionMenu) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------
|
||||
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(recommendFilesToMsg())) ;
|
||||
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return ;
|
||||
}//switch (type)
|
||||
}
|
||||
|
||||
contextMnu.exec(QCursor::pos()) ;
|
||||
GxsChannelDialog *channelDialog = dynamic_cast<GxsChannelDialog*>(MainWindow::getPage(MainWindow::Channels));
|
||||
|
||||
if(channelDialog != NULL)
|
||||
{
|
||||
QMenu shareChannelMenu(tr("Share on channel...")) ;
|
||||
shareChannelMenu.setIcon(QIcon(IMAGE_CHANNEL));
|
||||
|
||||
std::list<RsGroupMetaData> grp_metas ;
|
||||
channelDialog->getGroupList(grp_metas) ;
|
||||
|
||||
for(auto it(grp_metas.begin());it!=grp_metas.end();++it)
|
||||
if(IS_GROUP_PUBLISHER((*it).mSubscribeFlags))
|
||||
shareChannelMenu.addAction(QString::fromUtf8((*it).mGroupName.c_str()), this, SLOT(shareOnChannel()))->setData(QString::fromStdString((*it).mGroupId.toStdString())) ;
|
||||
|
||||
contextMnu.addMenu(&shareChannelMenu) ;
|
||||
contextMnu.exec(QCursor::pos()) ; // added here because the shareChannelMenu QMenu object is deleted afterwards
|
||||
}
|
||||
else
|
||||
contextMnu.exec(QCursor::pos()) ;
|
||||
}
|
||||
|
||||
void LocalSharedFilesDialog::shareOnChannel()
|
||||
{
|
||||
RsGxsGroupId groupId(qobject_cast<QAction*>(sender())->data().toString().toStdString());
|
||||
|
||||
GxsChannelDialog *channelDialog = dynamic_cast<GxsChannelDialog*>(MainWindow::getPage(MainWindow::Channels));
|
||||
|
||||
if(channelDialog == NULL)
|
||||
return ;
|
||||
|
||||
std::list<DirDetails> files_info ;
|
||||
|
||||
QList<RetroShareLink> file_links_list ;
|
||||
bool has_unhashed_files ;
|
||||
|
||||
copyLinks(getSelected(),false,file_links_list,has_unhashed_files) ;
|
||||
|
||||
channelDialog->shareOnChannel(groupId,file_links_list) ;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <set>
|
||||
#include "RsAutoUpdatePage.h"
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "ui_SharedFilesDialog.h"
|
||||
|
||||
class RetroshareDirModel;
|
||||
@ -68,10 +69,6 @@ private slots:
|
||||
void collView();
|
||||
void collOpen();
|
||||
|
||||
//== void showFrame(bool show);
|
||||
//== void showFrameRemote(bool show);
|
||||
//== void showFrameSplitted(bool show);
|
||||
|
||||
void recommendFilesToMsg();
|
||||
|
||||
void indicatorChanged(int index);
|
||||
@ -103,6 +100,7 @@ protected:
|
||||
|
||||
//QMenu* contextMnu2;
|
||||
|
||||
void copyLinks(const QModelIndexList& lst, bool remote, QList<RetroShareLink>& urls, bool& has_unhashed_files);
|
||||
void copyLink (const QModelIndexList& lst, bool remote);
|
||||
|
||||
void FilterItems();
|
||||
@ -161,6 +159,7 @@ class LocalSharedFilesDialog : public SharedFilesDialog
|
||||
void runCommandForFile();
|
||||
void tryToAddNewAssotiation();
|
||||
void forceCheck();
|
||||
void shareOnChannel();
|
||||
|
||||
QAction* fileAssotiationAction(const QString fileName);
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include <gui/common/FilesDefs.h>
|
||||
#include <gui/common/RsCollectionFile.h>
|
||||
#include <gui/common/RsCollection.h>
|
||||
#include <gui/common/RsUrlHandler.h>
|
||||
#include <gui/common/RSTreeView.h>
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
#include "xprogressbar.h"
|
||||
#include <gui/settings/rsharesettings.h>
|
||||
#include "util/misc.h"
|
||||
#include <gui/common/RsCollectionFile.h>
|
||||
#include <gui/common/RsCollection.h>
|
||||
#include "TransferUserNotify.h"
|
||||
#include "util/QtVersion.h"
|
||||
#include "util/RsFile.h"
|
||||
@ -652,7 +652,8 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
|
||||
QMenu contextMnu( this );
|
||||
|
||||
if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE)) add_PasteLink=true;
|
||||
if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE)) add_PasteLink=true;
|
||||
if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE_TREE)) add_PasteLink=true;
|
||||
|
||||
if(!items.empty())
|
||||
{
|
||||
@ -666,8 +667,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
|
||||
//Look only for first column == File List
|
||||
//Get Info for current item
|
||||
if (rsFiles->FileDetails(fileHash
|
||||
, RS_FILE_HINTS_DOWNLOAD, info)) {
|
||||
if (rsFiles->FileDetails(fileHash, RS_FILE_HINTS_DOWNLOAD, info)) {
|
||||
/*const uint32_t FT_STATE_FAILED = 0x0000;
|
||||
*const uint32_t FT_STATE_OKAY = 0x0001;
|
||||
*const uint32_t FT_STATE_WAITING = 0x0002;
|
||||
@ -677,22 +677,21 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
*const uint32_t FT_STATE_PAUSED = 0x0006;
|
||||
*const uint32_t FT_STATE_CHECKING_HASH = 0x0007;
|
||||
*/
|
||||
if (info.downloadStatus == FT_STATE_WAITING) {
|
||||
if (info.downloadStatus == FT_STATE_WAITING)
|
||||
atLeastOne_Waiting = true ;
|
||||
}//if (info.downloadStatus == FT_STATE_WAITING)
|
||||
if (info.downloadStatus == FT_STATE_DOWNLOADING) {
|
||||
|
||||
if (info.downloadStatus == FT_STATE_DOWNLOADING)
|
||||
atLeastOne_Downloading=true ;
|
||||
}//if (info.downloadStatus == FT_STATE_DOWNLOADING)
|
||||
|
||||
if (info.downloadStatus == FT_STATE_COMPLETE) {
|
||||
atLeastOne_Complete = true ;
|
||||
add_OpenFileOption = single ;
|
||||
}//if (info.downloadStatus == FT_STATE_COMPLETE)
|
||||
if (info.downloadStatus == FT_STATE_QUEUED) {
|
||||
}
|
||||
if (info.downloadStatus == FT_STATE_QUEUED)
|
||||
atLeastOne_Queued = true ;
|
||||
}//if(info.downloadStatus == FT_STATE_QUEUED)
|
||||
if (info.downloadStatus == FT_STATE_PAUSED) {
|
||||
|
||||
if (info.downloadStatus == FT_STATE_PAUSED)
|
||||
atLeastOne_Paused = true ;
|
||||
}//if (info.downloadStatus == FT_STATE_PAUSED)
|
||||
|
||||
size_t pos = info.fname.find_last_of('.') ;
|
||||
if (pos != std::string::npos) {
|
||||
@ -700,23 +699,23 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
if (misc::isPreviewable(info.fname.substr(pos + 1).c_str())) {
|
||||
add_PreviewOption = (info.downloadStatus != FT_STATE_COMPLETE) ;
|
||||
add_PlayOption = !add_PreviewOption ;
|
||||
}// if (misc::isPreviewable(info.fname.substr(pos + 1).c_str()))
|
||||
}
|
||||
// Check if the file is a collection
|
||||
if (RsCollectionFile::ExtensionString == info.fname.substr(pos + 1).c_str()) {
|
||||
if (RsCollection::ExtensionString == info.fname.substr(pos + 1).c_str()) {
|
||||
add_CollActions = (info.downloadStatus == FT_STATE_COMPLETE);
|
||||
}//if (RsCollectionFile::ExtensionString == info
|
||||
}// if(pos != std::string::npos)
|
||||
}
|
||||
}
|
||||
|
||||
}// if FileDetails
|
||||
}// for items iterate
|
||||
}// if (!items.empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (atLeastOne_Waiting || atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Paused) {
|
||||
contextMnu.addMenu( &prioritySpeedMenu) ;
|
||||
}
|
||||
if (atLeastOne_Queued) {
|
||||
contextMnu.addMenu( &priorityQueueMenu) ;
|
||||
}//if (atLeastOne_Queued)
|
||||
}
|
||||
|
||||
if ( (!items.empty())
|
||||
&& (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting || atLeastOne_Paused)) {
|
||||
@ -724,7 +723,7 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
|
||||
if (single) {
|
||||
contextMnu.addAction( renameFileAct) ;
|
||||
}//if (single)
|
||||
}
|
||||
|
||||
QMenu *directoryMenu = contextMnu.addMenu(QIcon(IMAGE_OPENFOLDER), tr("Set destination directory")) ;
|
||||
directoryMenu->addAction(specifyDestinationDirectoryAct) ;
|
||||
@ -745,27 +744,24 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
act->setData(QString::fromUtf8( (*it).filename.c_str() ) ) ;
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(setDestinationDirectory())) ;
|
||||
directoryMenu->addAction( act) ;
|
||||
}//for (std::list<SharedDirInfo>::const_iterator it
|
||||
}//if ( (!items.empty()) &&
|
||||
}
|
||||
}
|
||||
|
||||
if (atLeastOne_Paused) {
|
||||
if (atLeastOne_Paused)
|
||||
contextMnu.addAction(resumeAct) ;
|
||||
}//if (atLeastOne_Paused)
|
||||
if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting) {
|
||||
|
||||
if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting)
|
||||
contextMnu.addAction(pauseAct) ;
|
||||
}//if (atLeastOne_Downloading || atLeastOne_Queued || atLeastOne_Waiting)
|
||||
|
||||
if (!atLeastOne_Complete && !items.empty()) {
|
||||
contextMnu.addAction(forceCheckAct) ;
|
||||
contextMnu.addAction(cancelAct) ;
|
||||
}//if (!atLeastOne_Complete && !items.empty())
|
||||
if (add_PlayOption) {
|
||||
}
|
||||
if (add_PlayOption)
|
||||
contextMnu.addAction(playAct) ;
|
||||
}//if (add_PlayOption)
|
||||
|
||||
if (atLeastOne_Paused || atLeastOne_Downloading || atLeastOne_Complete || add_PlayOption) {
|
||||
contextMnu.addSeparator() ;//------------------------------------------------
|
||||
}//if (atLeastOne_Paused ||
|
||||
if (atLeastOne_Paused || atLeastOne_Downloading || atLeastOne_Complete || add_PlayOption)
|
||||
contextMnu.addSeparator() ;
|
||||
|
||||
if (single) {
|
||||
if (add_OpenFileOption) contextMnu.addAction( openFileAct) ;
|
||||
@ -773,20 +769,20 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
contextMnu.addAction( openFolderAct) ;
|
||||
contextMnu.addAction( detailsFileAct) ;
|
||||
contextMnu.addSeparator() ;//--------------------------------------------
|
||||
}//if (single)
|
||||
}
|
||||
|
||||
contextMnu.addAction( clearCompletedAct) ;
|
||||
contextMnu.addSeparator() ;//------------------------------------------------
|
||||
contextMnu.addSeparator() ;
|
||||
|
||||
if (add_CopyLink) {
|
||||
contextMnu.addAction( copyLinkAct) ;
|
||||
}//if (add_CopyLink)
|
||||
}
|
||||
if (add_PasteLink) {
|
||||
contextMnu.addAction( pasteLinkAct) ;
|
||||
}//if (add_PasteLink)
|
||||
}
|
||||
if (add_CopyLink || add_PasteLink) {
|
||||
contextMnu.addSeparator() ;//--------------------------------------------
|
||||
}//if (add_CopyLink || add_PasteLink)
|
||||
contextMnu.addSeparator() ;
|
||||
}
|
||||
|
||||
if (DLLFilterModel->rowCount()>0 ) {
|
||||
contextMnu.addAction( expandAllDLAct ) ;
|
||||
@ -1644,7 +1640,27 @@ void TransfersDialog::updateDetailsDialog()
|
||||
|
||||
void TransfersDialog::pasteLink()
|
||||
{
|
||||
RSLinkClipboard::process(RetroShareLink::TYPE_FILE);
|
||||
QList<RetroShareLink> links ;
|
||||
|
||||
// We want to capture and process all links at once here, because we're possibly pasting a large collection of files. So we first
|
||||
// merge all links into a single RsCollection and then process it.
|
||||
|
||||
RsCollection col ;
|
||||
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE_TREE);
|
||||
|
||||
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
|
||||
{
|
||||
FileTree *ft = FileTree::create((*it).radix().toStdString()) ;
|
||||
|
||||
col.merge_in(*ft) ;
|
||||
}
|
||||
links.clear();
|
||||
RSLinkClipboard::pasteLinks(links,RetroShareLink::TYPE_FILE);
|
||||
|
||||
for(QList<RetroShareLink>::const_iterator it(links.begin());it!=links.end();++it)
|
||||
col.merge_in((*it).name(),(*it).size(),RsFileHash((*it).hash().toStdString())) ;
|
||||
|
||||
col.downloadFiles();
|
||||
}
|
||||
|
||||
void TransfersDialog::getDLSelectedItems(std::set<RsFileHash> *ids, std::set<int> *rows)
|
||||
@ -2155,7 +2171,7 @@ void TransfersDialog::collCreate()
|
||||
dirVec.push_back(details);
|
||||
}//for (it = items.begin();
|
||||
|
||||
RsCollectionFile(dirVec).openNewColl(this);
|
||||
RsCollection(dirVec).openNewColl(this);
|
||||
}
|
||||
|
||||
void TransfersDialog::collModif()
|
||||
@ -2180,12 +2196,12 @@ void TransfersDialog::collModif()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
}//if (info.downloadStatus == FT_STATE_COMPLETE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::collView()
|
||||
@ -2210,12 +2226,12 @@ void TransfersDialog::collView()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath(), true);
|
||||
}//if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString))
|
||||
}//if (qinfo.exists())
|
||||
}//if (info.downloadStatus == FT_STATE_COMPLETE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::collOpen()
|
||||
@ -2240,8 +2256,8 @@ void TransfersDialog::collOpen()
|
||||
QFileInfo qinfo;
|
||||
qinfo.setFile(QString::fromUtf8(path.c_str()));
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
if (collection.load(qinfo.absoluteFilePath())) {
|
||||
collection.downloadFiles();
|
||||
return;
|
||||
@ -2252,95 +2268,24 @@ void TransfersDialog::collOpen()
|
||||
}
|
||||
}
|
||||
|
||||
RsCollectionFile collection;
|
||||
RsCollection collection;
|
||||
if (collection.load(this)) {
|
||||
collection.downloadFiles();
|
||||
}//if (collection.load(this))
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLSizeColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_SIZE)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_SIZE, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLCompleteColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_COMPLETED)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_COMPLETED, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLDLSpeedColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_DLSPEED)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_DLSPEED, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLProgressColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_PROGRESS)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_PROGRESS, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLSourcesColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_SOURCES)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_SOURCES, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLStatusColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_STATUS)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_STATUS, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLPriorityColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_PRIORITY)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_PRIORITY, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLRemainingColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_REMAINING)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_REMAINING, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLDownloadTimeColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_DOWNLOADTIME)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_DOWNLOADTIME, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLIDColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_ID)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_ID, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLLastDLColumn(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_LASTDL)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_LASTDL, !show);
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersDialog::setShowDLPath(bool show)
|
||||
{
|
||||
if ( (!ui.downloadList->isColumnHidden(COLUMN_PATH)) != show) {
|
||||
ui.downloadList->setColumnHidden(COLUMN_PATH, !show);
|
||||
}
|
||||
}
|
||||
void TransfersDialog::setShowDLSizeColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SIZE, !show); }
|
||||
void TransfersDialog::setShowDLCompleteColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_COMPLETED, !show); }
|
||||
void TransfersDialog::setShowDLDLSpeedColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_DLSPEED, !show); }
|
||||
void TransfersDialog::setShowDLProgressColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PROGRESS, !show); }
|
||||
void TransfersDialog::setShowDLSourcesColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_SOURCES, !show); }
|
||||
void TransfersDialog::setShowDLStatusColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_STATUS, !show); }
|
||||
void TransfersDialog::setShowDLPriorityColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_PRIORITY, !show); }
|
||||
void TransfersDialog::setShowDLRemainingColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_REMAINING, !show); }
|
||||
void TransfersDialog::setShowDLDownloadTimeColumn(bool show) { ui.downloadList->setColumnHidden(COLUMN_DOWNLOADTIME, !show); }
|
||||
void TransfersDialog::setShowDLIDColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_ID, !show); }
|
||||
void TransfersDialog::setShowDLLastDLColumn (bool show) { ui.downloadList->setColumnHidden(COLUMN_LASTDL, !show); }
|
||||
void TransfersDialog::setShowDLPath (bool show) { ui.downloadList->setColumnHidden(COLUMN_PATH, !show); }
|
||||
|
||||
void TransfersDialog::expandAllDL()
|
||||
{
|
||||
|
@ -103,7 +103,7 @@
|
||||
#include "gui/statistics/StatisticsWindow.h"
|
||||
|
||||
#include "gui/connect/ConnectFriendWizard.h"
|
||||
#include "gui/common/RsCollectionFile.h"
|
||||
#include "gui/common/RsCollection.h"
|
||||
#include "settings/rsettingswin.h"
|
||||
#include "settings/rsharesettings.h"
|
||||
#include "settings/WebuiPage.h"
|
||||
@ -141,6 +141,7 @@
|
||||
#define IMAGE_BLOGS ":/images/kblogger.png"
|
||||
#define IMAGE_DHT ":/images/dht16.png"
|
||||
|
||||
/*static*/ bool MainWindow::hiddenmode = false;
|
||||
|
||||
/*static*/ MainWindow *MainWindow::_instance = NULL;
|
||||
|
||||
@ -182,6 +183,8 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
|
||||
RsPeerDetails pd;
|
||||
if (rsPeers->getPeerDetails(rsPeers->getOwnId(), pd)) {
|
||||
nameAndLocation = QString("%1 (%2)").arg(QString::fromUtf8(pd.name.c_str())).arg(QString::fromUtf8(pd.location.c_str()));
|
||||
if(pd.netMode == RS_NETMODE_HIDDEN)
|
||||
hiddenmode = true;
|
||||
}
|
||||
|
||||
setWindowTitle(tr("RetroShare %1 a secure decentralized communication platform").arg(Rshare::retroshareVersion(true)) + " - " + nameAndLocation);
|
||||
@ -207,8 +210,9 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
|
||||
connect(ui->listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(setNewPage(int)));
|
||||
connect(ui->stackPages, SIGNAL(currentChanged(int)), this, SLOT(setNewPage(int)));
|
||||
|
||||
//ui->stackPages->setCurrentIndex(Settings->getLastPageInMainWindow());
|
||||
setNewPage(Settings->getLastPageInMainWindow());
|
||||
int lastpageindex = Settings->getLastPageInMainWindow();
|
||||
if(lastpageindex < ui->stackPages->count()) //Do not crash when a page was removed after last run
|
||||
setNewPage(lastpageindex);
|
||||
|
||||
ui->splitter->setStretchFactor(0, 0);
|
||||
ui->splitter->setStretchFactor(1, 1);
|
||||
@ -241,13 +245,17 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
|
||||
statusBar()->addWidget(peerstatus);
|
||||
|
||||
natstatus = new NATStatus();
|
||||
natstatus->setVisible(Settings->valueFromGroup("StatusBar", "ShowNAT", QVariant(true)).toBool());
|
||||
if(hiddenmode) natstatus->setVisible(false);
|
||||
else natstatus->setVisible(Settings->valueFromGroup("StatusBar", "ShowNAT", QVariant(true)).toBool());
|
||||
statusBar()->addWidget(natstatus);
|
||||
|
||||
natstatus->getNATStatus();
|
||||
|
||||
dhtstatus = new DHTStatus();
|
||||
dhtstatus->setVisible(Settings->valueFromGroup("StatusBar", "ShowDHT", QVariant(true)).toBool());
|
||||
if(hiddenmode) dhtstatus->setVisible(false);
|
||||
else dhtstatus->setVisible(Settings->valueFromGroup("StatusBar", "ShowDHT", QVariant(true)).toBool());
|
||||
statusBar()->addWidget(dhtstatus);
|
||||
|
||||
dhtstatus->getDHTStatus();
|
||||
|
||||
hashingstatus = new HashingStatus();
|
||||
hashingstatus->setVisible(Settings->valueFromGroup("StatusBar", "ShowHashing", QVariant(true)).toBool());
|
||||
statusBar()->addPermanentWidget(hashingstatus, 1);
|
||||
@ -702,11 +710,14 @@ void MainWindow::updateStatus()
|
||||
if (ratesstatus)
|
||||
ratesstatus->getRatesStatus(downKb, upKb);
|
||||
|
||||
if(!hiddenmode)
|
||||
{
|
||||
if (natstatus)
|
||||
natstatus->getNATStatus();
|
||||
|
||||
if (dhtstatus)
|
||||
dhtstatus->getDHTStatus();
|
||||
}
|
||||
|
||||
if (discstatus) {
|
||||
discstatus->update();
|
||||
@ -1020,7 +1031,7 @@ void MainWindow::newRsCollection()
|
||||
{
|
||||
std::vector <DirDetails> dirVec;
|
||||
|
||||
RsCollectionFile(dirVec).openNewColl(this);
|
||||
RsCollection(dirVec).openNewColl(this);
|
||||
}
|
||||
|
||||
/** Shows Share Manager */
|
||||
@ -1448,8 +1459,8 @@ void MainWindow::openRsCollection(const QString &filename)
|
||||
{
|
||||
QFileInfo qinfo(filename);
|
||||
if (qinfo.exists()) {
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollectionFile::ExtensionString)) {
|
||||
RsCollectionFile collection;
|
||||
if (qinfo.absoluteFilePath().endsWith(RsCollection::ExtensionString)) {
|
||||
RsCollection collection;
|
||||
collection.openColl(qinfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
@ -1576,10 +1587,13 @@ void MainWindow::setCompactStatusMode(bool compact)
|
||||
//statusComboBox: TODO Show only icon
|
||||
peerstatus->setCompactMode(compact);
|
||||
updateFriends();
|
||||
if(!hiddenmode)
|
||||
{
|
||||
natstatus->setCompactMode(compact);
|
||||
natstatus->getNATStatus();
|
||||
dhtstatus->setCompactMode(compact);
|
||||
dhtstatus->getDHTStatus();
|
||||
}
|
||||
hashingstatus->setCompactMode(compact);
|
||||
ratesstatus->setCompactMode(compact);
|
||||
//opModeStatus: TODO Show only ???
|
||||
|
@ -184,6 +184,8 @@ public:
|
||||
ToasterDisable *toasterDisableInstance();
|
||||
SysTrayStatus *sysTrayStatusInstance();
|
||||
|
||||
static bool hiddenmode;
|
||||
|
||||
public slots:
|
||||
void receiveNewArgs(QStringList args);
|
||||
void displayErrorMessage(int,int,const QString&) ;
|
||||
|
@ -1116,7 +1116,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
|
||||
|
||||
if (findData->mSecurityIpItem) {
|
||||
SecurityIpItem *securityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
|
||||
if (securityIpItem && securityIpItem->isSame(findData->mId1, findData->mId2, findData->mType)) {
|
||||
if (securityIpItem && securityIpItem->isSame(RsPeerId(findData->mId1), findData->mId2, findData->mId3, findData->mType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "util/TokenQueue.h"
|
||||
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *posted, const RsGxsGroupId& grpId, QWidget *parent):
|
||||
@ -35,7 +37,7 @@ PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *pos
|
||||
ui(new Ui::PostedCreatePostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
Settings->loadWidgetInformation(this);
|
||||
connect(ui->submitButton, SIGNAL(clicked()), this, SLOT(createPost()));
|
||||
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(close()));
|
||||
|
||||
@ -50,6 +52,7 @@ PostedCreatePostDialog::PostedCreatePostDialog(TokenQueue* tokenQ, RsPosted *pos
|
||||
|
||||
PostedCreatePostDialog::~PostedCreatePostDialog()
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -104,8 +104,6 @@ void PostedItem::setup()
|
||||
|
||||
ui->clearButton->hide();
|
||||
ui->readAndClearButton->hide();
|
||||
|
||||
ui->frame_notes->hide();
|
||||
}
|
||||
|
||||
bool PostedItem::setGroup(const RsPostedGroup &group, bool doFill)
|
||||
@ -278,11 +276,12 @@ void PostedItem::fill()
|
||||
|
||||
// FIX THIS UP LATER.
|
||||
ui->notes->setText(QString::fromUtf8(mPost.mNotes.c_str()));
|
||||
if(ui->notes->text().isEmpty())
|
||||
ui->frame_notes->hide();
|
||||
// differences between Feed or Top of Comment.
|
||||
if (mFeedHolder)
|
||||
{
|
||||
// feed.
|
||||
ui->frame_notes->hide();
|
||||
//frame_comment->show();
|
||||
ui->commentButton->show();
|
||||
|
||||
@ -303,14 +302,6 @@ void PostedItem::fill()
|
||||
else
|
||||
{
|
||||
// no feed.
|
||||
if(ui->notes->text().isEmpty())
|
||||
{
|
||||
ui->frame_notes->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->frame_notes->show();
|
||||
}
|
||||
//frame_comment->hide();
|
||||
ui->commentButton->hide();
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="newCommHLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
@ -327,30 +327,29 @@
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_notes">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<widget class="QLabel" name="notes">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>2</x>
|
||||
<y>2</y>
|
||||
<width>16</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="notes">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include <retroshare-gui/RsAutoUpdatePage.h>
|
||||
#include <gui/common/RsCollectionFile.h>
|
||||
#include <gui/common/RsCollection.h>
|
||||
#include <gui/common/RsUrlHandler.h>
|
||||
#include <gui/common/FilesDefs.h>
|
||||
#include <gui/common/GroupDefs.h>
|
||||
@ -1065,7 +1065,7 @@ void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndex
|
||||
std::vector <DirDetails> dirVec;
|
||||
getDirDetailsFromSelect(list, dirVec);
|
||||
|
||||
RsCollectionFile(dirVec).openNewColl(parent);
|
||||
RsCollection(dirVec).openNewColl(parent);
|
||||
}
|
||||
|
||||
void RetroshareDirModel::downloadSelected(const QModelIndexList &list)
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "msgs/MessageComposer.h"
|
||||
#include "util/misc.h"
|
||||
#include "common/PeerDefs.h"
|
||||
#include "common/RsCollectionFile.h"
|
||||
#include "common/RsCollection.h"
|
||||
#include <gui/common/RsUrlHandler.h>
|
||||
#include "gui/connect/ConnectFriendWizard.h"
|
||||
#include "gui/connect/ConfCertDialog.h"
|
||||
@ -58,6 +58,7 @@
|
||||
//#define DEBUG_RSLINK 1
|
||||
|
||||
#define HOST_FILE "file"
|
||||
#define HOST_COLLECTION "collection"
|
||||
#define HOST_EXTRAFILE "extra"
|
||||
#define HOST_PERSON "person"
|
||||
#define HOST_FORUM "forum"
|
||||
@ -68,13 +69,18 @@
|
||||
#define HOST_CERTIFICATE "certificate"
|
||||
#define HOST_PUBLIC_MSG "public_msg"
|
||||
#define HOST_IDENTITY "identity"
|
||||
#define HOST_REGEXP "file|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg|identity"
|
||||
#define HOST_REGEXP "file|collection|extra|person|forum|channel|posted|search|message|certificate|private_chat|public_msg|identity"
|
||||
|
||||
#define FILE_NAME "name"
|
||||
#define FILE_SIZE "size"
|
||||
#define FILE_HASH "hash"
|
||||
#define FILE_SOURCE "src"
|
||||
|
||||
#define COLLECTION_NAME "name"
|
||||
#define COLLECTION_SIZE "size"
|
||||
#define COLLECTION_DATA "radix"
|
||||
#define COLLECTION_COUNT "files"
|
||||
|
||||
#define PERSON_NAME "name"
|
||||
#define PERSON_HASH "hash"
|
||||
|
||||
@ -328,6 +334,20 @@ void RetroShareLink::fromUrl(const QUrl& url)
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.host() == HOST_COLLECTION) {
|
||||
bool ok;
|
||||
_type = TYPE_FILE_TREE;
|
||||
_radix = decodedQueryItemValue(urlQuery, COLLECTION_DATA);
|
||||
_name = decodedQueryItemValue(urlQuery, COLLECTION_NAME);
|
||||
_size = urlQuery.queryItemValue(COLLECTION_SIZE).toULongLong(&ok);
|
||||
_count = urlQuery.queryItemValue(COLLECTION_COUNT).toULongLong(&ok);
|
||||
|
||||
#ifdef DEBUG_RSLINK
|
||||
std::cerr << "Got a certificate link!!" << std::endl;
|
||||
#endif
|
||||
check() ;
|
||||
return;
|
||||
}
|
||||
if (url.host() == HOST_CERTIFICATE) {
|
||||
_type = TYPE_CERTIFICATE;
|
||||
_radix = decodedQueryItemValue(urlQuery, CERTIFICATE_RADIX);
|
||||
@ -400,6 +420,21 @@ RetroShareLink RetroShareLink::createFile(const QString& name, uint64_t size, co
|
||||
return link;
|
||||
}
|
||||
|
||||
RetroShareLink RetroShareLink::createCollection(const QString& name, uint64_t size, uint32_t count, const QString& radix_data)
|
||||
{
|
||||
RetroShareLink link;
|
||||
link.clear();
|
||||
|
||||
link._name = name;
|
||||
link._count = count;
|
||||
link._size = size;
|
||||
link._radix = radix_data ;
|
||||
link._type = TYPE_FILE_TREE;
|
||||
|
||||
link.check();
|
||||
|
||||
return link;
|
||||
}
|
||||
RetroShareLink RetroShareLink::createPublicMsgInvite(time_t time_stamp,const QString& issuer_pgp_id,const QString& hash)
|
||||
{
|
||||
RetroShareLink link;
|
||||
@ -608,6 +643,8 @@ void RetroShareLink::check()
|
||||
if(!checkSSLId(_SSLid))
|
||||
_valid = false; // no break! We also test file stuff below.
|
||||
/* fallthrough */
|
||||
case TYPE_FILE_TREE:
|
||||
|
||||
case TYPE_FILE:
|
||||
if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files?
|
||||
_valid = false;
|
||||
@ -615,7 +652,7 @@ void RetroShareLink::check()
|
||||
if(!checkName(_name))
|
||||
_valid = false;
|
||||
|
||||
if(!checkHash(_hash))
|
||||
if(!checkRadix64(_radix))
|
||||
_valid = false;
|
||||
break;
|
||||
|
||||
@ -717,6 +754,8 @@ QString RetroShareLink::title() const
|
||||
rsPeers->getGPGDetails(RsPgpId(_GPGid.toStdString()), detail) ;
|
||||
return QObject::tr("Click to send a private message to %1 (%2).").arg(QString::fromUtf8(detail.name.c_str())).arg(_GPGid) ;
|
||||
}
|
||||
case TYPE_FILE_TREE:
|
||||
return QObject::tr("Click to browse/download this file collection");
|
||||
case TYPE_EXTRAFILE:
|
||||
return QObject::tr("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size()));
|
||||
case TYPE_FILE:
|
||||
@ -860,6 +899,15 @@ QString RetroShareLink::toString() const
|
||||
|
||||
break;
|
||||
|
||||
case TYPE_FILE_TREE:
|
||||
url.setScheme(RSLINK_SCHEME);
|
||||
url.setHost(HOST_COLLECTION) ;
|
||||
urlQuery.addQueryItem(COLLECTION_NAME, encodeItem(_name));
|
||||
urlQuery.addQueryItem(COLLECTION_SIZE, QString::number(_size));
|
||||
urlQuery.addQueryItem(COLLECTION_DATA, encodeItem(_radix));
|
||||
urlQuery.addQueryItem(COLLECTION_COUNT, QString::number(_count));
|
||||
break;
|
||||
|
||||
case TYPE_CERTIFICATE:
|
||||
url.setScheme(RSLINK_SCHEME);
|
||||
url.setHost(HOST_CERTIFICATE) ;
|
||||
@ -882,9 +930,15 @@ QString RetroShareLink::niceName() const
|
||||
if (type() == TYPE_PERSON)
|
||||
return PeerDefs::rsid(name().toUtf8().constData(), RsPgpId(hash().toStdString()));
|
||||
|
||||
if(type() == TYPE_FILE_TREE)
|
||||
return QObject::tr("%1 (%2 files, %3)").arg(_name).arg(_count).arg(misc::friendlyUnit(_size));
|
||||
|
||||
if(type() == TYPE_IDENTITY)
|
||||
return QObject::tr("Identity link (name=%1, ID=%2)").arg(_name).arg(_hash) ;
|
||||
|
||||
if(type() == TYPE_FILE_TREE)
|
||||
return QObject::tr("File directory (Total %s) Click to browse/download this file collection").arg(misc::friendlyUnit(_size));
|
||||
|
||||
if(type() == TYPE_PUBLIC_MSG) {
|
||||
RsPeerDetails detail;
|
||||
rsPeers->getGPGDetails(RsPgpId(_GPGid.toStdString()), detail) ;
|
||||
@ -926,10 +980,10 @@ QString RetroShareLink::toHtmlSize() const
|
||||
{
|
||||
QString size = QString("(%1)").arg(misc::friendlyUnit(_size));
|
||||
|
||||
if (type() == TYPE_FILE && RsCollectionFile::isCollectionFile(name())) {
|
||||
if (type() == TYPE_FILE && RsCollection::isCollectionFile(name())) {
|
||||
FileInfo finfo;
|
||||
if (rsFiles->FileDetails(RsFileHash(hash().toStdString()), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) {
|
||||
RsCollectionFile collection;
|
||||
RsCollection collection;
|
||||
if (collection.load(QString::fromUtf8(finfo.path.c_str()), false)) {
|
||||
size += QString(" [%1]").arg(misc::friendlyUnit(collection.size()));
|
||||
}
|
||||
@ -1095,6 +1149,7 @@ static void processList(const QStringList &list, const QString &textSingular, co
|
||||
case TYPE_SEARCH:
|
||||
case TYPE_MESSAGE:
|
||||
case TYPE_IDENTITY:
|
||||
case TYPE_FILE_TREE:
|
||||
case TYPE_CERTIFICATE:
|
||||
case TYPE_PUBLIC_MSG:
|
||||
case TYPE_PRIVATE_CHAT:
|
||||
@ -1336,6 +1391,16 @@ static void processList(const QStringList &list, const QString &textSingular, co
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_FILE_TREE:
|
||||
{
|
||||
FileTree *ft = FileTree::create(link.radix().toStdString()) ;
|
||||
|
||||
RsCollection(*ft).downloadFiles() ;
|
||||
|
||||
delete ft;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_PERSON:
|
||||
{
|
||||
#ifdef DEBUG_RSLINK
|
||||
@ -1347,34 +1412,6 @@ static void processList(const QStringList &list, const QString &textSingular, co
|
||||
PGPKeyDialog::showIt(detail.gpg_id,PGPKeyDialog::PageDetails) ;
|
||||
else
|
||||
personNotFound.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
|
||||
|
||||
// needNotifySuccess = true;
|
||||
|
||||
// RsPeerDetails detail;
|
||||
// if (rsPeers->getGPGDetails(RsPgpId(link.hash().toStdString()), detail))
|
||||
// {
|
||||
// if (RsPgpId(detail.gpg_id) == rsPeers->getGPGOwnId()) {
|
||||
// // it's me, do nothing
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (detail.accept_connection) {
|
||||
// // peer connection is already accepted
|
||||
// personExist.append(PeerDefs::rsid(detail));
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (rsPeers->addFriend(RsPeerId(), RsPgpId(link.hash().toStdString()))) {
|
||||
// ConfCertDialog::loadAll();
|
||||
// personAdded.append(PeerDefs::rsid(detail));
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// personFailed.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// personNotFound.append(PeerDefs::rsid(link.name().toUtf8().constData(), RsPgpId(link.hash().toStdString())));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1679,17 +1716,17 @@ void RSLinkClipboard::copyLinks(const QList<RetroShareLink>& links)
|
||||
QApplication::clipboard()->setText(res) ;
|
||||
}
|
||||
|
||||
void RSLinkClipboard::pasteLinks(QList<RetroShareLink> &links)
|
||||
void RSLinkClipboard::pasteLinks(QList<RetroShareLink> &links,RetroShareLink::enumType type)
|
||||
{
|
||||
return parseClipboard(links);
|
||||
return parseClipboard(links,type);
|
||||
}
|
||||
|
||||
void RSLinkClipboard::parseClipboard(QList<RetroShareLink> &links)
|
||||
void RSLinkClipboard::parseClipboard(QList<RetroShareLink> &links,RetroShareLink::enumType type)
|
||||
{
|
||||
// parse clipboard for links.
|
||||
//
|
||||
QString text = QApplication::clipboard()->text() ;
|
||||
parseText(text, links);
|
||||
parseText(text, links,type);
|
||||
}
|
||||
|
||||
QString RSLinkClipboard::toString()
|
||||
@ -1734,26 +1771,18 @@ bool RSLinkClipboard::empty(RetroShareLink::enumType type /* = RetroShareLink::T
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ int RSLinkClipboard::process(RetroShareLink::enumType type /* = RetroShareLink::TYPE_UNKNOWN*/, uint flag /* = RSLINK_PROCESS_NOTIFY_ALL*/)
|
||||
int RSLinkClipboard::process(RetroShareLink::enumType type /* = RetroShareLink::TYPE_UNKNOWN*/, uint flag /* = RSLINK_PROCESS_NOTIFY_ALL*/)
|
||||
{
|
||||
QList<RetroShareLink> links;
|
||||
pasteLinks(links);
|
||||
pasteLinks(links,type);
|
||||
|
||||
QList<RetroShareLink> linksToProcess;
|
||||
for (int i = 0; i < links.size(); ++i) {
|
||||
if (links[i].valid() && (type == RetroShareLink::TYPE_UNKNOWN || links[i].type() == type)) {
|
||||
linksToProcess.append(links[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (linksToProcess.isEmpty()) {
|
||||
if (links.isEmpty())
|
||||
return 0;
|
||||
}
|
||||
|
||||
return RetroShareLink::process(linksToProcess, flag);
|
||||
return RetroShareLink::process(links, flag);
|
||||
}
|
||||
|
||||
void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links)
|
||||
void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links,RetroShareLink::enumType type )
|
||||
{
|
||||
links.clear();
|
||||
|
||||
@ -1768,7 +1797,7 @@ void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links)
|
||||
QString url(text.mid(pos, rx.matchedLength()));
|
||||
RetroShareLink link(url);
|
||||
|
||||
if(link.valid())
|
||||
if(link.valid() && (type == RetroShareLink::TYPE_UNKNOWN || type == link.type()))
|
||||
{
|
||||
// check that the link is not already in the list:
|
||||
bool already = false ;
|
||||
|
@ -69,7 +69,8 @@ class RetroShareLink
|
||||
TYPE_PRIVATE_CHAT = 0x09,
|
||||
TYPE_PUBLIC_MSG = 0x0a,
|
||||
TYPE_POSTED = 0x0b,
|
||||
TYPE_IDENTITY = 0x0c
|
||||
TYPE_IDENTITY = 0x0c,
|
||||
TYPE_FILE_TREE = 0x0d
|
||||
};
|
||||
|
||||
public:
|
||||
@ -80,6 +81,7 @@ class RetroShareLink
|
||||
static RetroShareLink createIdentity(const RsGxsId& gxs_id,const QString& name,const QString& radix_data) ;
|
||||
static RetroShareLink createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id);
|
||||
static RetroShareLink createFile(const QString& name, uint64_t size, const QString& hash);
|
||||
static RetroShareLink createCollection(const QString& name, uint64_t size,uint32_t count,const QString& radix_data);
|
||||
static RetroShareLink createPublicMsgInvite(time_t time_stamp,const QString& pgp_id,const QString& hash) ;
|
||||
static RetroShareLink createPerson(const RsPgpId &id);
|
||||
static RetroShareLink createCertificate(const RsPeerId &ssl_id) ;
|
||||
@ -167,6 +169,7 @@ class RetroShareLink
|
||||
QString _encrypted_chat_info ; // encrypted data string for the recipient of a chat invite
|
||||
time_t _time_stamp ; // time stamp at which the link will expire.
|
||||
QString _radix_group_data;
|
||||
uint32_t _count ;
|
||||
|
||||
unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...)
|
||||
};
|
||||
@ -189,7 +192,7 @@ class RSLinkClipboard
|
||||
// Get the liste of pasted links, either from the internal RS links, or by default
|
||||
// from the clipboard.
|
||||
//
|
||||
static void pasteLinks(QList<RetroShareLink> &links) ;
|
||||
static void pasteLinks(QList<RetroShareLink> &links,RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
|
||||
|
||||
// Produces a list of links with no html structure.
|
||||
static QString toString() ;
|
||||
@ -212,10 +215,10 @@ class RSLinkClipboard
|
||||
//
|
||||
static int process(RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN, uint flag = RSLINK_PROCESS_NOTIFY_ALL);
|
||||
|
||||
static void parseText(QString text, QList<RetroShareLink> &links) ;
|
||||
static void parseText(QString text, QList<RetroShareLink> &links, RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
|
||||
|
||||
private:
|
||||
static void parseClipboard(QList<RetroShareLink> &links) ;
|
||||
static void parseClipboard(QList<RetroShareLink> &links, RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN) ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -111,7 +111,7 @@ ChatWidget::ChatWidget(QWidget *parent) :
|
||||
ui->searchButton->setFixedSize(buttonSize);
|
||||
ui->searchButton->setIconSize(iconSize);
|
||||
ui->sendButton->setFixedHeight(iconHeight);
|
||||
ui->sendButton->setIconSize(iconSize);
|
||||
ui->sendButton->setIconSize(iconSize);
|
||||
|
||||
//Initialize search
|
||||
iCharToStartSearch=Settings->getChatSearchCharToStartSearch();
|
||||
@ -295,6 +295,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title)
|
||||
this->title = title;
|
||||
|
||||
ui->titleLabel->setText(RsHtml::plainText(title));
|
||||
ui->chatTextEdit->setMaxBytes(this->maxMessageSize() - 200);
|
||||
|
||||
RsPeerId ownId = rsPeers->getOwnId();
|
||||
setName(QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()));
|
||||
@ -452,6 +453,25 @@ void ChatWidget::processSettings(bool load)
|
||||
Settings->endGroup();
|
||||
}
|
||||
|
||||
uint32_t ChatWidget::maxMessageSize()
|
||||
{
|
||||
uint32_t maxMessageSize = 0;
|
||||
switch (chatType()) {
|
||||
case CHATTYPE_UNKNOWN:
|
||||
break;
|
||||
case CHATTYPE_PRIVATE:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_PRIVATE);
|
||||
break;
|
||||
case CHATTYPE_LOBBY:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY);
|
||||
break;
|
||||
case CHATTYPE_DISTANT:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_DISTANT);
|
||||
break;
|
||||
}
|
||||
return maxMessageSize;
|
||||
}
|
||||
|
||||
bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (obj == ui->textBrowser || obj == ui->textBrowser->viewport()
|
||||
@ -1169,20 +1189,7 @@ void ChatWidget::updateLenOfChatTextEdit()
|
||||
RsHtml::optimizeHtml(chatWidget, text);
|
||||
std::wstring msg = text.toStdWString();
|
||||
|
||||
uint32_t maxMessageSize = 0;
|
||||
switch (chatType()) {
|
||||
case CHATTYPE_UNKNOWN:
|
||||
break;
|
||||
case CHATTYPE_PRIVATE:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_PRIVATE);
|
||||
break;
|
||||
case CHATTYPE_LOBBY:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY);
|
||||
break;
|
||||
case CHATTYPE_DISTANT:
|
||||
maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_DISTANT);
|
||||
break;
|
||||
}
|
||||
uint32_t maxMessageSize = this->maxMessageSize();
|
||||
|
||||
int charRemains = 0;
|
||||
if (maxMessageSize > 0) {
|
||||
@ -1561,7 +1568,8 @@ void ChatWidget::addExtraPicture()
|
||||
QString file;
|
||||
if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg)", file)) {
|
||||
QString encodedImage;
|
||||
if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480)) {
|
||||
uint32_t maxMessageSize = this->maxMessageSize();
|
||||
if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480, maxMessageSize - 200)) { //-200 for the html stuff
|
||||
QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage);
|
||||
ui->chatTextEdit->textCursor().insertFragment(fragment);
|
||||
}
|
||||
|
@ -198,6 +198,8 @@ private:
|
||||
void setColorAndFont(bool both);
|
||||
void processSettings(bool load);
|
||||
|
||||
uint32_t maxMessageSize();
|
||||
|
||||
void completeNickname(bool reverse);
|
||||
QAbstractItemModel *modelFromPeers();
|
||||
|
||||
|
@ -11,21 +11,12 @@
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="textChatHLayout">
|
||||
<property name="spacing">
|
||||
@ -46,16 +37,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="chatTextFrameVLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -131,16 +113,7 @@
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="infoFrameHLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -308,7 +281,7 @@ border-image: url(:/images/closepressed.png)
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<property name="placeholderText" stdset="0">
|
||||
<string>Type a message here</string>
|
||||
</property>
|
||||
</widget>
|
||||
@ -326,16 +299,7 @@ border-image: url(:/images/closepressed.png)
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="toolBarFrameHLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -436,6 +400,41 @@ border-image: url(:/images/closepressed.png)
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="searchButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/search.png</normaloff>:/icons/png/search.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LineEditClear" name="leSearch"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="markButton">
|
||||
<property name="sizePolicy">
|
||||
@ -465,9 +464,6 @@ border-image: url(:/images/closepressed.png)
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LineEditClear" name="leSearch"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="searchBefore">
|
||||
<property name="minimumSize">
|
||||
@ -520,38 +516,6 @@ border-image: url(:/images/closepressed.png)
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="searchButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/search.png</normaloff>:/icons/png/search.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="notifyButton">
|
||||
<property name="focusPolicy">
|
||||
@ -581,16 +545,7 @@ border-image: url(:/images/closepressed.png)
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="pluginButtonFrameHLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</layout>
|
||||
@ -688,16 +643,7 @@ border-image: url(:/images/closepressed.png)
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="titleBarFrameHLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -778,16 +724,7 @@ border-image: url(:/images/closepressed.png)
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="pluginTitleFrameHLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</layout>
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "FilesDefs.h"
|
||||
#include "RsCollectionFile.h"
|
||||
#include "RsCollection.h"
|
||||
|
||||
static QString getInfoFromFilename(const QString& filename, bool anyForUnknown, bool image)
|
||||
{
|
||||
@ -54,7 +54,7 @@ static QString getInfoFromFilename(const QString& filename, bool anyForUnknown,
|
||||
return image ? ":/images/FileTypeDocument.png" : QApplication::translate("FilesDefs", "Document");
|
||||
} else if (ext == "pdf") {
|
||||
return image ? ":/images/mimetypes/pdf.png" : QApplication::translate("FilesDefs", "Document");
|
||||
} else if (ext == RsCollectionFile::ExtensionString) {
|
||||
} else if (ext == RsCollection::ExtensionString) {
|
||||
return image ? ":/images/mimetypes/rscollection-16.png" : QApplication::translate("FilesDefs", "RetroShare collection file");
|
||||
} else if (ext == "sub" || ext == "srt") {
|
||||
return image ? ":/images/FileTypeAny.png" : QApplication::translate("FilesDefs", "Subtitles");
|
||||
|
@ -69,7 +69,7 @@ void MimeTextEdit::insertFromMimeData(const QMimeData* source)
|
||||
QImage image = qvariant_cast<QImage>(source->imageData());
|
||||
if (image.isNull() == false) {
|
||||
QString encodedImage;
|
||||
if (RsHtml::makeEmbeddedImage(image, encodedImage, 640*480)) {
|
||||
if (RsHtml::makeEmbeddedImage(image, encodedImage, 640*480, mMaxBytes)) {
|
||||
QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage);
|
||||
textCursor().insertFragment(fragment);
|
||||
return;
|
||||
|
@ -50,6 +50,8 @@ public:
|
||||
QColor textColorQuote() const { return highliter->textColorQuote();}
|
||||
bool onlyPlainText() const {return mOnlyPlainText;}
|
||||
|
||||
void setMaxBytes(int limit) {mMaxBytes = limit;}
|
||||
|
||||
public slots:
|
||||
void setTextColorQuote(QColor textColorQuote) { highliter->setTextColorQuote(textColorQuote);}
|
||||
void setOnlyPlainText(bool bOnlyPlainText) {mOnlyPlainText = bOnlyPlainText;}
|
||||
@ -83,6 +85,7 @@ private:
|
||||
QList<QAction*> mContextMenuActions;
|
||||
RsSyntaxHighlighter *highliter;
|
||||
bool mOnlyPlainText;
|
||||
int mMaxBytes = -1; //limit content size, for pasting images
|
||||
};
|
||||
|
||||
#endif // MIMETEXTEDIT_H
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <stdexcept>
|
||||
#include <retroshare/rsfiles.h>
|
||||
|
||||
#include "RsCollectionFile.h"
|
||||
#include "RsCollection.h"
|
||||
#include "RsCollectionDialog.h"
|
||||
#include "util/misc.h"
|
||||
|
||||
@ -36,28 +36,41 @@
|
||||
#include <QMessageBox>
|
||||
#include <QIcon>
|
||||
|
||||
const QString RsCollectionFile::ExtensionString = QString("rscollection") ;
|
||||
// #define COLLECTION_DEBUG 1
|
||||
|
||||
RsCollectionFile::RsCollectionFile(QObject *parent)
|
||||
const QString RsCollection::ExtensionString = QString("rscollection") ;
|
||||
|
||||
RsCollection::RsCollection(QObject *parent)
|
||||
: QObject(parent), _xml_doc("RsCollection")
|
||||
{
|
||||
_root = _xml_doc.createElement("RsCollection");
|
||||
_xml_doc.appendChild(_root);
|
||||
}
|
||||
|
||||
RsCollectionFile::RsCollectionFile(const std::vector<DirDetails>& file_infos, QObject *parent)
|
||||
RsCollection::RsCollection(const FileTree& fr)
|
||||
: _xml_doc("RsCollection")
|
||||
{
|
||||
_root = _xml_doc.createElement("RsCollection");
|
||||
_xml_doc.appendChild(_root);
|
||||
|
||||
recursAddElements(_xml_doc,fr,0,_root) ;
|
||||
}
|
||||
|
||||
RsCollection::RsCollection(const std::vector<DirDetails>& file_infos, QObject *parent)
|
||||
: QObject(parent), _xml_doc("RsCollection")
|
||||
{
|
||||
QDomElement root = _xml_doc.createElement("RsCollection");
|
||||
_xml_doc.appendChild(root);
|
||||
_root = _xml_doc.createElement("RsCollection");
|
||||
_xml_doc.appendChild(_root);
|
||||
|
||||
for(uint32_t i = 0;i<file_infos.size();++i)
|
||||
recursAddElements(_xml_doc,file_infos[i],root) ;
|
||||
recursAddElements(_xml_doc,file_infos[i],_root) ;
|
||||
}
|
||||
|
||||
RsCollectionFile::~RsCollectionFile()
|
||||
RsCollection::~RsCollection()
|
||||
{
|
||||
}
|
||||
|
||||
void RsCollectionFile::downloadFiles() const
|
||||
void RsCollection::downloadFiles() const
|
||||
{
|
||||
// print out the element names of all elements that are direct children
|
||||
// of the outermost element.
|
||||
@ -87,17 +100,35 @@ static QString purifyFileName(const QString& input,bool& bad)
|
||||
return output ;
|
||||
}
|
||||
|
||||
void RsCollectionFile::recursCollectColFileInfos(const QDomElement& e,std::vector<ColFileInfo>& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const
|
||||
void RsCollection::merge_in(const QString& fname,uint64_t size,const RsFileHash& hash)
|
||||
{
|
||||
ColFileInfo info ;
|
||||
info.type = DIR_TYPE_FILE ;
|
||||
info.name = fname ;
|
||||
info.size = size ;
|
||||
info.hash = QString::fromStdString(hash.toStdString()) ;
|
||||
|
||||
recursAddElements(_xml_doc,info,_root) ;
|
||||
}
|
||||
void RsCollection::merge_in(const FileTree& tree)
|
||||
{
|
||||
recursAddElements(_xml_doc,tree,0,_root) ;
|
||||
}
|
||||
|
||||
void RsCollection::recursCollectColFileInfos(const QDomElement& e,std::vector<ColFileInfo>& colFileInfos,const QString& current_path, bool bad_chars_in_parent) const
|
||||
{
|
||||
QDomNode n = e.firstChild() ;
|
||||
|
||||
#ifdef COLLECTION_DEBUG
|
||||
std::cerr << "Parsing element " << e.tagName().toStdString() << std::endl;
|
||||
#endif
|
||||
|
||||
while(!n.isNull())
|
||||
{
|
||||
QDomElement ee = n.toElement(); // try to convert the node to an element.
|
||||
|
||||
#ifdef COLLECTION_DEBUG
|
||||
std::cerr << " Seeing child " << ee.tagName().toStdString() << std::endl;
|
||||
#endif
|
||||
|
||||
if(ee.tagName() == QString("File"))
|
||||
{
|
||||
@ -139,7 +170,7 @@ void RsCollectionFile::recursCollectColFileInfos(const QDomElement& e,std::vecto
|
||||
}
|
||||
|
||||
|
||||
void RsCollectionFile::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e) const
|
||||
void RsCollection::recursAddElements(QDomDocument& doc,const DirDetails& details,QDomElement& e) const
|
||||
{
|
||||
if (details.type == DIR_TYPE_FILE)
|
||||
{
|
||||
@ -175,7 +206,7 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const DirDetails& det
|
||||
}
|
||||
}
|
||||
|
||||
void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const
|
||||
void RsCollection::recursAddElements(QDomDocument& doc,const ColFileInfo& colFileInfo,QDomElement& e) const
|
||||
{
|
||||
if (colFileInfo.type == DIR_TYPE_FILE)
|
||||
{
|
||||
@ -186,7 +217,7 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& co
|
||||
f.setAttribute(QString("size"),QString::number(colFileInfo.size)) ;
|
||||
|
||||
e.appendChild(f) ;
|
||||
}
|
||||
}
|
||||
else if (colFileInfo.type == DIR_TYPE_DIR)
|
||||
{
|
||||
QDomElement d = doc.createElement("Directory") ;
|
||||
@ -194,21 +225,47 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const ColFileInfo& co
|
||||
d.setAttribute(QString("name"),colFileInfo.name) ;
|
||||
|
||||
for (std::vector<ColFileInfo>::const_iterator it = colFileInfo.children.begin(); it != colFileInfo.children.end(); ++it)
|
||||
{
|
||||
recursAddElements(doc,(*it),d) ;
|
||||
}
|
||||
|
||||
e.appendChild(d) ;
|
||||
}
|
||||
}
|
||||
|
||||
void RsCollection::recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const
|
||||
{
|
||||
std::vector<uint32_t> subdirs ;
|
||||
std::vector<FileTree::FileData> subfiles ;
|
||||
std::string name;
|
||||
|
||||
if(!ft.getDirectoryContent(index,name,subdirs,subfiles))
|
||||
return ;
|
||||
|
||||
QDomElement d = doc.createElement("Directory") ;
|
||||
d.setAttribute(QString("name"),QString::fromUtf8(name.c_str())) ;
|
||||
e.appendChild(d) ;
|
||||
|
||||
for (uint32_t i=0;i<subdirs.size();++i)
|
||||
recursAddElements(doc,ft,subdirs[i],d) ;
|
||||
|
||||
for(uint32_t i=0;i<subfiles.size();++i)
|
||||
{
|
||||
QDomElement f = doc.createElement("File") ;
|
||||
|
||||
f.setAttribute(QString("name"),QString::fromUtf8(subfiles[i].name.c_str())) ;
|
||||
f.setAttribute(QString("sha1"),QString::fromStdString(subfiles[i].hash.toStdString())) ;
|
||||
f.setAttribute(QString("size"),QString::number(subfiles[i].size)) ;
|
||||
|
||||
d.appendChild(f) ;
|
||||
}
|
||||
}
|
||||
|
||||
static void showErrorBox(const QString& fileName, const QString& error)
|
||||
{
|
||||
QMessageBox mb(QMessageBox::Warning, QObject::tr("Failed to process collection file"), QObject::tr("The collection file %1 could not be opened.\nReported error is: \n\n%2").arg(fileName).arg(error), QMessageBox::Ok);
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
bool RsCollectionFile::load(const QString& fileName, bool showError /* = true*/)
|
||||
bool RsCollection::load(const QString& fileName, bool showError /* = true*/)
|
||||
{
|
||||
|
||||
if (!checkFile(fileName,showError)) return false;
|
||||
@ -235,10 +292,10 @@ bool RsCollectionFile::load(const QString& fileName, bool showError /* = true*/)
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this
|
||||
bool RsCollectionFile::checkFile(const QString& fileName, bool showError)
|
||||
bool RsCollection::checkFile(const QString& fileName, bool showError)
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
@ -305,11 +362,10 @@ bool RsCollectionFile::checkFile(const QString& fileName, bool showError)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RsCollectionFile::load(QWidget *parent)
|
||||
bool RsCollection::load(QWidget *parent)
|
||||
{
|
||||
QString fileName;
|
||||
if (!misc::getOpenFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")", fileName))
|
||||
if (!misc::getOpenFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Open collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
|
||||
return false;
|
||||
|
||||
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
|
||||
@ -317,7 +373,7 @@ bool RsCollectionFile::load(QWidget *parent)
|
||||
return load(fileName, true);
|
||||
}
|
||||
|
||||
bool RsCollectionFile::save(const QString& fileName) const
|
||||
bool RsCollection::save(const QString& fileName) const
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
@ -337,14 +393,14 @@ bool RsCollectionFile::save(const QString& fileName) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsCollectionFile::save(QWidget *parent) const
|
||||
bool RsCollection::save(QWidget *parent) const
|
||||
{
|
||||
QString fileName;
|
||||
if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")", fileName))
|
||||
if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE, QApplication::translate("RsCollectionFile", "Create collection file"), QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")", fileName))
|
||||
return false;
|
||||
|
||||
if (!fileName.endsWith("." + RsCollectionFile::ExtensionString))
|
||||
fileName += "." + RsCollectionFile::ExtensionString ;
|
||||
if (!fileName.endsWith("." + RsCollection::ExtensionString))
|
||||
fileName += "." + RsCollection::ExtensionString ;
|
||||
|
||||
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
|
||||
|
||||
@ -352,17 +408,17 @@ bool RsCollectionFile::save(QWidget *parent) const
|
||||
}
|
||||
|
||||
|
||||
bool RsCollectionFile::openNewColl(QWidget *parent)
|
||||
bool RsCollection::openNewColl(QWidget *parent)
|
||||
{
|
||||
QString fileName;
|
||||
if(!misc::getSaveFileName(parent, RshareSettings::LASTDIR_EXTRAFILE
|
||||
, QApplication::translate("RsCollectionFile", "Create collection file")
|
||||
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")"
|
||||
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")"
|
||||
, fileName,0, QFileDialog::DontConfirmOverwrite))
|
||||
return false;
|
||||
|
||||
if (!fileName.endsWith("." + RsCollectionFile::ExtensionString))
|
||||
fileName += "." + RsCollectionFile::ExtensionString ;
|
||||
if (!fileName.endsWith("." + RsCollection::ExtensionString))
|
||||
fileName += "." + RsCollection::ExtensionString ;
|
||||
|
||||
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
|
||||
|
||||
@ -419,7 +475,7 @@ bool RsCollectionFile::openNewColl(QWidget *parent)
|
||||
return _saved;
|
||||
}
|
||||
|
||||
bool RsCollectionFile::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/)
|
||||
bool RsCollection::openColl(const QString& fileName, bool readOnly /* = false */, bool showError /* = true*/)
|
||||
{
|
||||
if (load(fileName, showError)) {
|
||||
std::vector<ColFileInfo> colFileInfos ;
|
||||
@ -433,11 +489,11 @@ bool RsCollectionFile::openColl(const QString& fileName, bool readOnly /* = fals
|
||||
delete rcd;
|
||||
|
||||
return _saved;
|
||||
}//if (load(fileName, showError))
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qulonglong RsCollectionFile::size()
|
||||
qulonglong RsCollection::size()
|
||||
{
|
||||
QDomElement docElem = _xml_doc.documentElement();
|
||||
|
||||
@ -453,14 +509,14 @@ qulonglong RsCollectionFile::size()
|
||||
return size;
|
||||
}
|
||||
|
||||
bool RsCollectionFile::isCollectionFile(const QString &fileName)
|
||||
bool RsCollection::isCollectionFile(const QString &fileName)
|
||||
{
|
||||
QString ext = QFileInfo(fileName).suffix().toLower();
|
||||
|
||||
return (ext == RsCollectionFile::ExtensionString);
|
||||
return (ext == RsCollection::ExtensionString);
|
||||
}
|
||||
|
||||
void RsCollectionFile::saveColl(std::vector<ColFileInfo> colFileInfos, const QString &fileName)
|
||||
void RsCollection::saveColl(std::vector<ColFileInfo> colFileInfos, const QString &fileName)
|
||||
{
|
||||
|
||||
QDomElement root = _xml_doc.elementsByTagName("RsCollection").at(0).toElement();
|
@ -56,27 +56,29 @@ public:
|
||||
};
|
||||
Q_DECLARE_METATYPE(ColFileInfo)
|
||||
|
||||
class RsCollectionFile : public QObject
|
||||
class RsCollection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
RsCollectionFile(QObject *parent = 0) ;
|
||||
// create from list of files and directories
|
||||
RsCollectionFile(const std::vector<DirDetails>& file_entries, QObject *parent = 0) ;
|
||||
virtual ~RsCollectionFile() ;
|
||||
RsCollection(QObject *parent = 0) ;
|
||||
// create from list of files and directories
|
||||
RsCollection(const std::vector<DirDetails>& file_entries, QObject *parent = 0) ;
|
||||
RsCollection(const FileTree& fr);
|
||||
virtual ~RsCollection() ;
|
||||
|
||||
void merge_in(const QString& fname,uint64_t size,const RsFileHash& hash) ;
|
||||
void merge_in(const FileTree& tree) ;
|
||||
|
||||
static const QString ExtensionString ;
|
||||
|
||||
|
||||
|
||||
// Loads file from disk.
|
||||
bool load(QWidget *parent);
|
||||
// Loads file from disk.
|
||||
bool load(QWidget *parent);
|
||||
bool load(const QString& fileName, bool showError = true);
|
||||
|
||||
// Save to disk
|
||||
bool save(QWidget *parent) const ;
|
||||
// Save to disk
|
||||
bool save(QWidget *parent) const ;
|
||||
bool save(const QString& fileName) const ;
|
||||
|
||||
// Open new collection
|
||||
@ -84,28 +86,31 @@ public:
|
||||
// Open existing collection
|
||||
bool openColl(const QString& fileName, bool readOnly = false, bool showError = true);
|
||||
|
||||
// Download the content.
|
||||
void downloadFiles() const ;
|
||||
// Download the content.
|
||||
void downloadFiles() const ;
|
||||
|
||||
qulonglong size();
|
||||
qulonglong size();
|
||||
|
||||
static bool isCollectionFile(const QString& fileName);
|
||||
|
||||
private slots:
|
||||
void saveColl(std::vector<ColFileInfo> colFileInfos, const QString& fileName);
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
void recursAddElements(QDomDocument&,const DirDetails&,QDomElement&) const ;
|
||||
void recursAddElements(QDomDocument&,const DirDetails&,QDomElement&) const ;
|
||||
void recursAddElements(QDomDocument&,const ColFileInfo&,QDomElement&) const;
|
||||
void recursAddElements(QDomDocument& doc,const FileTree& ft,uint32_t index,QDomElement& e) const;
|
||||
|
||||
void recursCollectColFileInfos(const QDomElement&,std::vector<ColFileInfo>& colFileInfos,const QString& current_dir,bool bad_chars_in_parent) const ;
|
||||
// check that the file is a valid rscollection file, and not a lol bomb or some shit like this
|
||||
static bool checkFile(const QString &fileName, bool showError);
|
||||
|
||||
QDomDocument _xml_doc ;
|
||||
QDomDocument _xml_doc ;
|
||||
QString _fileName ;
|
||||
bool _saved;
|
||||
QDomElement _root ;
|
||||
|
||||
friend class RsCollectionDialog ;
|
||||
friend class RsCollectionDialog ;
|
||||
};
|
||||
|
@ -23,13 +23,14 @@
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QTextEdit>
|
||||
#include <QDir>
|
||||
#include <QKeyEvent>
|
||||
#include <QDateTime>
|
||||
#include <QInputDialog>
|
||||
#include "RsCollectionDialog.h"
|
||||
#include "RsCollectionFile.h"
|
||||
#include "RsCollection.h"
|
||||
#include "util/misc.h"
|
||||
#define COLUMN_FILE 0
|
||||
#define COLUMN_FILEPATH 1
|
||||
@ -50,6 +51,7 @@
|
||||
|
||||
#define MAX_FILE_ADDED_BEFORE_ASK 500 //Number of file added in Recursive mode before asking to continue
|
||||
|
||||
#define IMAGE_SEARCH ":/icons/svg/magnifying-glass.svg"
|
||||
|
||||
/**
|
||||
* @brief The FSMSortFilterProxyModel class sort directory before file.
|
||||
@ -138,7 +140,23 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
|
||||
|
||||
|
||||
ui.headerFrame->setHeaderImage(QPixmap(":/images/library64.png"));
|
||||
ui.headerFrame->setHeaderText(tr("Collection Editor"));
|
||||
|
||||
if(creation)
|
||||
{
|
||||
ui.headerFrame->setHeaderText(tr("Collection Editor"));
|
||||
ui.downloadFolder_LE->hide();
|
||||
ui.downloadFolder_LB->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.headerFrame->setHeaderText(tr("Download files"));
|
||||
ui.downloadFolder_LE->show();
|
||||
ui.downloadFolder_LB->show();
|
||||
|
||||
ui.downloadFolder_LE->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str())) ;
|
||||
|
||||
QObject::connect(ui.downloadFolder_LE,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(openDestinationDirectoryMenu(QPoint)));
|
||||
}
|
||||
|
||||
// 1 - add all elements to the list.
|
||||
|
||||
@ -209,6 +227,46 @@ RsCollectionDialog::RsCollectionDialog(const QString& collectionFileName
|
||||
QMessageBox::warning(NULL,tr("Bad filenames have been cleaned"),tr("Some filenames or directory names contained forbidden characters.\nCharacters <b>\",|,/,\\,<,>,*,?</b> will be replaced by '_'.\n Concerned files are listed in red.")) ;
|
||||
}
|
||||
|
||||
void RsCollectionDialog::openDestinationDirectoryMenu(QPoint)
|
||||
{
|
||||
QMenu contextMnu( this );
|
||||
|
||||
// pop a menu with existing entries and also a custom entry
|
||||
// Now get the list of existing directories.
|
||||
|
||||
std::list< SharedDirInfo> dirs ;
|
||||
rsFiles->getSharedDirectories( dirs) ;
|
||||
|
||||
for (std::list<SharedDirInfo>::const_iterator it(dirs.begin());it!=dirs.end();++it){
|
||||
// Check for existence of directory name
|
||||
QFile directory( QString::fromUtf8((*it).filename.c_str())) ;
|
||||
|
||||
if (!directory.exists()) continue ;
|
||||
if (!(directory.permissions() & QFile::WriteOwner)) continue ;
|
||||
|
||||
contextMnu.addAction(QString::fromUtf8((*it).filename.c_str()), this, SLOT(setDestinationDirectory()))->setData(QString::fromUtf8( (*it).filename.c_str() ) ) ;
|
||||
}
|
||||
|
||||
contextMnu.addAction( QIcon(IMAGE_SEARCH),tr("Specify..."),this,SLOT(chooseDestinationDirectory()));
|
||||
|
||||
contextMnu.exec(QCursor::pos()) ;
|
||||
}
|
||||
|
||||
void RsCollectionDialog::setDestinationDirectory()
|
||||
{
|
||||
QString dest_dir(qobject_cast<QAction*>(sender())->data().toString()) ;
|
||||
ui.downloadFolder_LE->setText(dest_dir) ;
|
||||
}
|
||||
|
||||
void RsCollectionDialog::chooseDestinationDirectory()
|
||||
{
|
||||
QString dest_dir = QFileDialog::getExistingDirectory(this,tr("Choose directory")) ;
|
||||
|
||||
if(dest_dir.isNull())
|
||||
return ;
|
||||
|
||||
ui.downloadFolder_LE->setText(dest_dir) ;
|
||||
}
|
||||
/**
|
||||
* @brief RsCollectionDialog::~RsCollectionDialog
|
||||
*/
|
||||
@ -243,26 +301,26 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
|
||||
for (it = selectedItems.begin(); it != selectedItems.end(); ++it) {
|
||||
if ((*it)->checkState(COLUMN_FILE) != checkState)
|
||||
(*it)->setCheckState(COLUMN_FILE, checkState);
|
||||
}//for (it
|
||||
}//if (item)
|
||||
}
|
||||
}
|
||||
|
||||
return true; // eat event
|
||||
}//if (keyEvent && keyEvent->key() == Qt::Key_Space)
|
||||
}
|
||||
|
||||
if (keyEvent && (keyEvent->key() == Qt::Key_Delete)) {
|
||||
// Delete pressed
|
||||
remove();
|
||||
return true; // eat event
|
||||
}//if (keyEvent && keyEvent->key() == Qt::Key_Delete)
|
||||
}
|
||||
|
||||
if (keyEvent && (keyEvent->key() == Qt::Key_Plus)) {
|
||||
// Plus pressed
|
||||
makeDir();
|
||||
return true; // eat event
|
||||
}//if (keyEvent && keyEvent->key() == Qt::Key_Plus)
|
||||
}
|
||||
|
||||
}//if (event->type() == QEvent::KeyPress)
|
||||
}//if (obj == ui._fileEntriesTW)
|
||||
}
|
||||
}
|
||||
|
||||
if (obj == ui._systemFileTW) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
@ -277,9 +335,9 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
|
||||
}
|
||||
|
||||
return true; // eat event
|
||||
}//if (keyEvent && keyEvent->key() == Qt::Key_Enter...
|
||||
}//if (event->type() == QEvent::KeyPress)
|
||||
}//if (obj == ui._systemFileTW)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pass the event on to the parent class
|
||||
return QDialog::eventFilter(obj, event);
|
||||
@ -452,7 +510,7 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
|
||||
item->setToolTip(COLUMN_FILEC, tr("Real File Count=%1").arg(1));
|
||||
item->setData(COLUMN_FILEC, ROLE_FILEC, 1);
|
||||
item->setData(COLUMN_FILEC, ROLE_SELFILEC, 1);
|
||||
}//if (colFileInfo.type==DIR_TYPE_DIR
|
||||
}
|
||||
item->setFont(COLUMN_FILE, font);
|
||||
|
||||
if (colFileInfo.filename_has_wrong_characters)
|
||||
@ -487,12 +545,12 @@ bool RsCollectionDialog::addChild(QTreeWidgetItem* parent, const std::vector<Col
|
||||
itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentSelFileCount));
|
||||
|
||||
itemParent = itemParent->parent();
|
||||
}//while (itemParent)
|
||||
}//if (itemParent)
|
||||
}//if (colFileInfo.type==DIR_TYPE_FILE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
founds.push_back(item);
|
||||
}//(founds.empty())
|
||||
}
|
||||
|
||||
if (!founds.empty()) {
|
||||
|
||||
@ -591,12 +649,12 @@ void RsCollectionDialog::changeFileName()
|
||||
QString fileName;
|
||||
if(!misc::getSaveFileName(this, RshareSettings::LASTDIR_EXTRAFILE
|
||||
, QApplication::translate("RsCollectionFile", "Create collection file")
|
||||
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollectionFile::ExtensionString + ")"
|
||||
, QApplication::translate("RsCollectionFile", "Collection files") + " (*." + RsCollection::ExtensionString + ")"
|
||||
, fileName,0, QFileDialog::DontConfirmOverwrite))
|
||||
return;
|
||||
|
||||
if (!fileName.endsWith("." + RsCollectionFile::ExtensionString))
|
||||
fileName += "." + RsCollectionFile::ExtensionString ;
|
||||
if (!fileName.endsWith("." + RsCollection::ExtensionString))
|
||||
fileName += "." + RsCollection::ExtensionString ;
|
||||
|
||||
std::cerr << "Got file name: " << fileName.toStdString() << std::endl;
|
||||
|
||||
@ -604,7 +662,7 @@ void RsCollectionDialog::changeFileName()
|
||||
|
||||
if(file.exists())
|
||||
{
|
||||
RsCollectionFile collFile;
|
||||
RsCollection collFile;
|
||||
if (!collFile.checkFile(fileName,true)) return;
|
||||
|
||||
QMessageBox mb;
|
||||
@ -624,7 +682,7 @@ void RsCollectionDialog::changeFileName()
|
||||
if (qddOldFile.setContent(&file)) {
|
||||
QDomElement docOldElem = qddOldFile.elementsByTagName("RsCollection").at(0).toElement();
|
||||
collFile.recursCollectColFileInfos(docOldElem,_newColFileInfos,QString(),false);
|
||||
}//(qddOldFile.setContent(&file))
|
||||
}
|
||||
|
||||
} else if (mb.clickedButton()==btnCancel) {
|
||||
return;
|
||||
@ -636,7 +694,7 @@ void RsCollectionDialog::changeFileName()
|
||||
//create a new empty file to check if name if good.
|
||||
if (!file.open(QFile::WriteOnly)) return;
|
||||
file.remove();
|
||||
}//if(file.exists())
|
||||
}
|
||||
|
||||
_fileName = fileName;
|
||||
|
||||
@ -686,7 +744,7 @@ void RsCollectionDialog::addRecursive(bool recursive)
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}//if (fileInfo.isDir())
|
||||
}
|
||||
if (fileInfo.isFile()){
|
||||
fileToHash.append(fileInfo.absoluteFilePath());
|
||||
++count;
|
||||
@ -694,9 +752,9 @@ void RsCollectionDialog::addRecursive(bool recursive)
|
||||
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
|
||||
else
|
||||
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),"");
|
||||
}//if (fileInfo.isFile())
|
||||
}//if (index.column()==0)
|
||||
}//foreach (QModelIndex index, milSelectionList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process Dirs
|
||||
QTreeWidgetItem *item = NULL;
|
||||
@ -705,8 +763,8 @@ void RsCollectionDialog::addRecursive(bool recursive)
|
||||
if (item) {
|
||||
while (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() != DIR_TYPE_DIR) {
|
||||
item = item->parent();//Only Dir as Parent
|
||||
}//while
|
||||
}//if (item)
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
while (index < dirToAdd.count())
|
||||
@ -722,7 +780,7 @@ void RsCollectionDialog::addRecursive(bool recursive)
|
||||
//QMap is ordered, so we get parent before child
|
||||
//Iterator is moved inside this function
|
||||
processItem(dirToAdd, index, root);
|
||||
}//while (index < dirToAdd.count())
|
||||
}
|
||||
|
||||
//Update liste before attach files to be sure when file is hashed, parent directory exists.
|
||||
updateList();
|
||||
@ -736,9 +794,9 @@ void RsCollectionDialog::addRecursive(bool recursive)
|
||||
} else if(item) {
|
||||
if (item->data(COLUMN_HASH, ROLE_NAME) != "") {
|
||||
it.value() = item->text(COLUMN_FILEPATH);
|
||||
}//if (item->data(COLUMN_HASH, ROLE_NAME) != "")
|
||||
}//if (dirToAdd.contains(path))
|
||||
}//for (QHash<QString,QString>::Iterator it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process Files once all done
|
||||
ui._hashBox->addAttachments(fileToHash,RS_FILE_REQ_ANONYMOUS_ROUTING /*, 0*/);
|
||||
@ -781,13 +839,13 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent
|
||||
default:
|
||||
// should never be reached
|
||||
break;
|
||||
}//switch (ret)
|
||||
}
|
||||
}
|
||||
if (fileInfo.isDir()) {
|
||||
dirToAdd.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
|
||||
++count;
|
||||
if (!addAllChild(fileInfo, dirToAdd, fileToHash, count)) return false;
|
||||
}//if (fileInfo.isDir())
|
||||
}
|
||||
if (fileInfo.isFile()){
|
||||
fileToHash.append(fileInfo.absoluteFilePath());
|
||||
++count;
|
||||
@ -795,8 +853,8 @@ bool RsCollectionDialog::addAllChild(QFileInfo &fileInfoParent
|
||||
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),fileInfo.absolutePath());
|
||||
else
|
||||
_listOfFilesAddedInDir.insert(fileInfo.absoluteFilePath(),"");
|
||||
}//if (fileInfo.isFile())
|
||||
}//foreach (QFileInfo fileInfo, dirParent.entryInfoList())
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -821,10 +879,10 @@ void RsCollectionDialog::remove()
|
||||
item->setSelected(false);
|
||||
} else {
|
||||
listDir += item->data(COLUMN_HASH, ROLE_NAME).toString() +"<br>";
|
||||
}//if (listDir.contains(item->data(COLUMN_HASH, ROLE_PATH).toString()))
|
||||
}//if (item->data(COLUMN_HASH, ROLE_TYPE).toUInt() == DIR_TYPE_DIR)
|
||||
}//if (item != getRootItem())
|
||||
}//for (int curs = 0; curs < count; ++curs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If directories, ask to remove them or not
|
||||
if (!listDir.isEmpty()){
|
||||
@ -870,14 +928,14 @@ void RsCollectionDialog::remove()
|
||||
case QMessageBox::Cancel: {
|
||||
delete msgBox;
|
||||
return;
|
||||
}//case QMessageBox::Cancel:
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// should never be reached
|
||||
break;
|
||||
}//switch (ret)
|
||||
}
|
||||
delete msgBox;
|
||||
}//if (!listDir.isEmpty())
|
||||
}
|
||||
|
||||
//Remove wanted items
|
||||
int leftItem = 0;
|
||||
@ -966,7 +1024,7 @@ void RsCollectionDialog::processItem(QMap<QString, QString> &dirToAdd
|
||||
} else {
|
||||
_newColFileInfos.push_back(newChild);
|
||||
}
|
||||
}//(index < count)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1006,13 +1064,13 @@ void RsCollectionDialog::makeDir()
|
||||
default:
|
||||
// should never be reached
|
||||
break;
|
||||
}//switch (ret)
|
||||
}//if (badChar)
|
||||
}
|
||||
}
|
||||
} else {//if (ok && !childName.isEmpty())
|
||||
return;
|
||||
}//if (ok && !childName.isEmpty())
|
||||
}
|
||||
|
||||
}//while (!nameOK)
|
||||
}
|
||||
|
||||
// Process all selected items
|
||||
int count = ui._fileEntriesTW->selectedItems().count();
|
||||
@ -1040,8 +1098,8 @@ void RsCollectionDialog::makeDir()
|
||||
if (item == getRootItem()) newChild.path = "";
|
||||
|
||||
_newColFileInfos.push_back(newChild);
|
||||
}//if (item)
|
||||
}//for (; curs < count; ++curs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateList();
|
||||
@ -1074,7 +1132,7 @@ void RsCollectionDialog::fileHashingFinished(QList<HashedFile> hashedFiles)
|
||||
//File Added in directory, find its parent
|
||||
colFileInfo.path = _listOfFilesAddedInDir.value(hashedFile.filepath,"");
|
||||
_listOfFilesAddedInDir.remove(hashedFile.filepath);
|
||||
}//if (_listOfFilesAddedInDir.value(hashedFile.filepath,"")!="")
|
||||
}
|
||||
|
||||
_newColFileInfos.push_back(colFileInfo);
|
||||
|
||||
@ -1112,7 +1170,7 @@ void RsCollectionDialog::itemChanged(QTreeWidgetItem *item, int col)
|
||||
itemParent->setText(COLUMN_FILEC, QString("%1").arg(parentFileCount));
|
||||
|
||||
itemParent = itemParent->parent();
|
||||
}//while (itemParent)
|
||||
}
|
||||
|
||||
updateSizes() ;
|
||||
|
||||
@ -1222,7 +1280,7 @@ void RsCollectionDialog::download()
|
||||
{
|
||||
std::cerr << "Downloading!" << std::endl;
|
||||
|
||||
QString dldir = QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()) ;
|
||||
QString dldir = ui.downloadFolder_LE->text();
|
||||
|
||||
std::cerr << "downloading all these files:" << std::endl;
|
||||
|
||||
@ -1258,8 +1316,8 @@ void RsCollectionDialog::download()
|
||||
std::list<RsPeerId>());
|
||||
} else {//if (item->checkState(COLUMN_FILE) == Qt::Checked)
|
||||
std::cerr<<"Skipping file : " << item->data(COLUMN_HASH,ROLE_NAME).toString().toStdString() << std::endl;
|
||||
}//if (item->checkState(COLUMN_FILE) == Qt::Checked)
|
||||
}//while ((item = *itemIterator) != NULL)
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
****************************************************************/
|
||||
|
||||
#include "ui_RsCollectionDialog.h"
|
||||
#include "RsCollectionFile.h"
|
||||
#include "RsCollection.h"
|
||||
#include <QFileSystemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
@ -49,6 +49,9 @@ private slots:
|
||||
void add() ;
|
||||
void addRecursive() ;
|
||||
void remove() ;
|
||||
void chooseDestinationDirectory();
|
||||
void setDestinationDirectory();
|
||||
void openDestinationDirectoryMenu(QPoint pt);
|
||||
void processItem(QMap<QString, QString> &dirToAdd
|
||||
, int &index
|
||||
, ColFileInfo &parent
|
||||
|
@ -6,10 +6,13 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>693</width>
|
||||
<height>525</height>
|
||||
<width>969</width>
|
||||
<height>778</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Collection</string>
|
||||
</property>
|
||||
@ -67,19 +70,7 @@
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="_frameInfo">
|
||||
<property name="sizePolicy">
|
||||
@ -403,7 +394,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_removeDuplicate_CB">
|
||||
<property name="text">
|
||||
@ -424,6 +415,26 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadFolder_LB">
|
||||
<property name="text">
|
||||
<string>Destination:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="downloadFolder_LE">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Right click to change download directory</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="_cancel_PB">
|
||||
<property name="text">
|
||||
|
@ -22,14 +22,14 @@
|
||||
#include <stdexcept>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include "RsCollectionFile.h"
|
||||
#include "RsCollection.h"
|
||||
#include "RsUrlHandler.h"
|
||||
|
||||
bool RsUrlHandler::openUrl(const QUrl& url)
|
||||
{
|
||||
if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollectionFile::ExtensionString))
|
||||
if(url.scheme() == QString("file") && url.toLocalFile().endsWith("."+RsCollection::ExtensionString))
|
||||
{
|
||||
RsCollectionFile collection ;
|
||||
RsCollection collection ;
|
||||
if(collection.load(url.toLocalFile()))
|
||||
{
|
||||
collection.downloadFiles() ;
|
||||
|
@ -83,7 +83,7 @@ ConfCertDialog::ConfCertDialog(const RsPeerId& id, const RsPgpId &pgp_id, QWidge
|
||||
{
|
||||
/* Invoke Qt Designer generated QObject setup routine */
|
||||
ui.setupUi(this);
|
||||
|
||||
Settings->loadWidgetInformation(this);
|
||||
ui.headerFrame->setHeaderImage(QPixmap(":/images/user/identityinfo64.png"));
|
||||
//ui.headerFrame->setHeaderText(tr("Friend node details"));
|
||||
|
||||
@ -105,6 +105,7 @@ ConfCertDialog::ConfCertDialog(const RsPeerId& id, const RsPgpId &pgp_id, QWidge
|
||||
|
||||
ConfCertDialog::~ConfCertDialog()
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
QMap<RsPeerId, ConfCertDialog*>::iterator it = instances_ssl.find(peerId);
|
||||
if (it != instances_ssl.end())
|
||||
instances_ssl.erase(it);
|
||||
|
@ -475,33 +475,17 @@ void ConnectFriendWizard::initializePage(int id)
|
||||
else
|
||||
ui->addKeyToKeyring_CB->setToolTip(tr("Check this to add the key to your keyring\nThis might be useful for sending\ndistant messages to this peer\neven if you don't make friends.")) ;
|
||||
|
||||
//set the radio button to sign the GPG key
|
||||
if (peerDetails.accept_connection && !peerDetails.ownsign) {
|
||||
//gpg key connection is already accepted, don't propose to accept it again
|
||||
ui->signGPGCheckBox->setChecked(false);
|
||||
ui->acceptNoSignGPGCheckBox->hide();
|
||||
ui->acceptNoSignGPGCheckBox->setChecked(false);
|
||||
}
|
||||
if (!peerDetails.accept_connection && peerDetails.ownsign) {
|
||||
//gpg key is already signed, don't propose to sign it again
|
||||
if(tmp_det.accept_connection) {
|
||||
ui->acceptNoSignGPGCheckBox->setChecked(true);
|
||||
ui->signGPGCheckBox->hide();
|
||||
ui->signGPGCheckBox->setChecked(false);
|
||||
ui->acceptNoSignGPGCheckBox->setEnabled(false);
|
||||
ui->acceptNoSignGPGCheckBox->setToolTip(tr("This key is already on your trusted list"));
|
||||
}
|
||||
if (!peerDetails.accept_connection && !peerDetails.ownsign) {
|
||||
ui->acceptNoSignGPGCheckBox->setChecked(true);
|
||||
ui->signGPGCheckBox->show();
|
||||
ui->signGPGCheckBox->setChecked(false);
|
||||
ui->acceptNoSignGPGCheckBox->show();
|
||||
}
|
||||
if (peerDetails.accept_connection && peerDetails.ownsign) {
|
||||
ui->acceptNoSignGPGCheckBox->setChecked(false);
|
||||
ui->acceptNoSignGPGCheckBox->hide();
|
||||
ui->signGPGCheckBox->setChecked(false);
|
||||
ui->signGPGCheckBox->hide();
|
||||
ui->alreadyRegisteredLabel->show();
|
||||
} else {
|
||||
else
|
||||
ui->alreadyRegisteredLabel->hide();
|
||||
if(tmp_det.ownsign) {
|
||||
ui->signGPGCheckBox->setChecked(true);
|
||||
ui->signGPGCheckBox->setEnabled(false);
|
||||
ui->signGPGCheckBox->setToolTip(tr("You have already signed this key"));
|
||||
}
|
||||
|
||||
QString trustString;
|
||||
|
@ -65,7 +65,7 @@ PGPKeyDialog::PGPKeyDialog(const RsPeerId& id, const RsPgpId &pgp_id, QWidget *p
|
||||
{
|
||||
/* Invoke Qt Designer generated QObject setup routine */
|
||||
ui.setupUi(this);
|
||||
|
||||
Settings->loadWidgetInformation(this);
|
||||
// if(id.isNull())
|
||||
// ui._useOldFormat_CB->setChecked(true) ;
|
||||
// else
|
||||
@ -100,6 +100,7 @@ PGPKeyDialog::PGPKeyDialog(const RsPeerId& id, const RsPgpId &pgp_id, QWidget *p
|
||||
|
||||
PGPKeyDialog::~PGPKeyDialog()
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
QMap<RsPgpId, PGPKeyDialog*>::iterator it = instances_pgp.find(pgpId);
|
||||
if (it != instances_pgp.end())
|
||||
instances_pgp.erase(it);
|
||||
|
@ -79,9 +79,9 @@ void SecurityIpItem::setup()
|
||||
updateItem();
|
||||
}
|
||||
|
||||
bool SecurityIpItem::isSame(const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type)
|
||||
bool SecurityIpItem::isSame(const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type)
|
||||
{
|
||||
if (mType == type && mIpAddr == ipAddr && mIpAddrReported == ipAddrReported) {
|
||||
if (mType == type && mSslId==sslId && mIpAddr == ipAddr && mIpAddrReported == ipAddrReported) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
|
||||
void updateItemStatic();
|
||||
|
||||
bool isSame(const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type);
|
||||
bool isSame(const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, uint32_t type);
|
||||
|
||||
protected:
|
||||
/* FeedItem */
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsgxscircles.h>
|
||||
|
||||
#include <gui/settings/rsharesettings.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// Control of Publish Signatures.
|
||||
@ -66,7 +68,7 @@ GxsGroupDialog::GxsGroupDialog(TokenQueue *tokenExternalQueue, uint32_t enableFl
|
||||
{
|
||||
/* Invoke the Qt Designer generated object setup routine */
|
||||
ui.setupUi(this);
|
||||
|
||||
|
||||
mInternalTokenQueue = NULL;
|
||||
|
||||
init();
|
||||
@ -87,6 +89,7 @@ GxsGroupDialog::GxsGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *t
|
||||
|
||||
GxsGroupDialog::~GxsGroupDialog()
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
if (mInternalTokenQueue) {
|
||||
delete(mInternalTokenQueue);
|
||||
}
|
||||
@ -134,6 +137,7 @@ void GxsGroupDialog::init()
|
||||
ui.personal_required->setChecked(true) ; // this is always true
|
||||
|
||||
initMode();
|
||||
Settings->loadWidgetInformation(this);
|
||||
}
|
||||
|
||||
QIcon GxsGroupDialog::serviceWindowIcon()
|
||||
|
@ -121,6 +121,13 @@ GxsGroupFrameDialog::~GxsGroupFrameDialog()
|
||||
delete(ui);
|
||||
}
|
||||
|
||||
void GxsGroupFrameDialog::getGroupList(std::list<RsGroupMetaData>& group_list)
|
||||
{
|
||||
group_list = mCachedGroupMetas ;
|
||||
|
||||
if(group_list.empty())
|
||||
requestGroupSummary();
|
||||
}
|
||||
void GxsGroupFrameDialog::initUi()
|
||||
{
|
||||
registerHelpButton(ui->helpButton, getHelpString(),pageName()) ;
|
||||
@ -927,6 +934,8 @@ void GxsGroupFrameDialog::loadGroupSummary(const uint32_t &token)
|
||||
RsUserdata *userdata = NULL;
|
||||
loadGroupSummaryToken(token, groupInfo, userdata);
|
||||
|
||||
mCachedGroupMetas = groupInfo ;
|
||||
|
||||
insertGroupsData(groupInfo, userdata);
|
||||
|
||||
mStateHelper->setLoading(TOKEN_TYPE_GROUP_SUMMARY, false);
|
||||
|
@ -81,6 +81,8 @@ public:
|
||||
|
||||
virtual QString getHelpString() const =0;
|
||||
|
||||
virtual void getGroupList(std::list<RsGroupMetaData>& groups) ;
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
virtual void updateDisplay(bool complete);
|
||||
@ -197,6 +199,8 @@ private:
|
||||
|
||||
/** Qt Designer generated object */
|
||||
Ui::GxsGroupFrameDialog *ui;
|
||||
|
||||
std::list<RsGroupMetaData> mCachedGroupMetas;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -50,7 +50,7 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId
|
||||
{
|
||||
/* Invoke the Qt Designer generated object setup routine */
|
||||
setupUi(this);
|
||||
|
||||
Settings->loadWidgetInformation(this);
|
||||
mChannelQueue = new TokenQueue(rsGxsChannels->getTokenService(), this);
|
||||
|
||||
headerFrame->setHeaderImage(QPixmap(":/images/channels.png"));
|
||||
@ -95,6 +95,7 @@ CreateGxsChannelMsg::CreateGxsChannelMsg(const RsGxsGroupId &cId, RsGxsMessageId
|
||||
|
||||
CreateGxsChannelMsg::~CreateGxsChannelMsg()
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
#ifdef CHANNELS_FRAME_CATCHER
|
||||
delete fCatcher;
|
||||
#endif
|
||||
@ -411,6 +412,11 @@ void CreateGxsChannelMsg::addExtraFile()
|
||||
}
|
||||
}
|
||||
|
||||
void CreateGxsChannelMsg::addHtmlText(const QString& text)
|
||||
{
|
||||
msgEdit->setHtml(text) ;
|
||||
}
|
||||
|
||||
void CreateGxsChannelMsg::addAttachment(const std::string &path)
|
||||
{
|
||||
/* add a SubFileItem to the attachment section */
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
/** Default Destructor */
|
||||
~CreateGxsChannelMsg();
|
||||
|
||||
void addHtmlText(const QString& text) ;
|
||||
void addAttachment(const std::string &path);
|
||||
void addAttachment(const RsFileHash &hash, const std::string &fname, uint64_t size, bool local, const RsPeerId &srcId,bool assume_file_ready = false);
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="channelPostTab">
|
||||
<attribute name="title">
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "GxsChannelDialog.h"
|
||||
#include "GxsChannelGroupDialog.h"
|
||||
#include "GxsChannelPostsWidget.h"
|
||||
#include "CreateGxsChannelMsg.h"
|
||||
#include "GxsChannelUserNotify.h"
|
||||
#include "gui/gxs/GxsGroupShareKey.h"
|
||||
#include "gui/feeds/GxsChannelPostItem.h"
|
||||
@ -76,6 +77,20 @@ UserNotify *GxsChannelDialog::getUserNotify(QObject *parent)
|
||||
return new GxsChannelUserNotify(rsGxsChannels, parent);
|
||||
}
|
||||
|
||||
void GxsChannelDialog::shareOnChannel(const RsGxsGroupId& channel_id,const QList<RetroShareLink>& file_links)
|
||||
{
|
||||
std::cerr << "Sharing file link on channel " << channel_id << ": Not yet implemented!" << std::endl;
|
||||
|
||||
CreateGxsChannelMsg *msgDialog = new CreateGxsChannelMsg(channel_id) ;
|
||||
|
||||
QString txt ;
|
||||
for(QList<RetroShareLink>::const_iterator it(file_links.begin());it!=file_links.end();++it)
|
||||
txt += (*it).toHtml() + "\n" ;
|
||||
|
||||
msgDialog->addHtmlText(txt);
|
||||
msgDialog->show();
|
||||
}
|
||||
|
||||
QString GxsChannelDialog::text(TextType type)
|
||||
{
|
||||
switch (type) {
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
|
||||
virtual UserNotify *getUserNotify(QObject *parent);
|
||||
|
||||
void shareOnChannel(const RsGxsGroupId& channel_id, const QList<RetroShareLink>& file_link) ;
|
||||
|
||||
protected:
|
||||
/* GxsGroupFrameDialog */
|
||||
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_CHANNEL; }
|
||||
|
@ -75,6 +75,8 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
|
||||
connect(ui->subscribeToolButton, SIGNAL(subscribe(bool)), this, SLOT(subscribeGroup(bool)));
|
||||
connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
|
||||
|
||||
ui->postButton->setText(tr("Add new post"));
|
||||
|
||||
/* add filter actions */
|
||||
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), FILTER_TITLE, tr("Search Title"));
|
||||
ui->filterLineEdit->addFilter(QIcon(), tr("Message"), FILTER_MSG, tr("Search Message"));
|
||||
|
@ -169,6 +169,9 @@
|
||||
<property name="toolTip">
|
||||
<string>Post to Channel</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add new post</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/mail_send.png</normaloff>:/images/mail_send.png</iconset>
|
||||
@ -179,6 +182,9 @@
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -210,6 +210,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
|
||||
connect(ui->newmessageButton, SIGNAL(clicked()), this, SLOT(replytoforummessage()));
|
||||
connect(ui->newthreadButton, SIGNAL(clicked()), this, SLOT(createthread()));
|
||||
|
||||
ui->newmessageButton->setText(tr("Reply"));
|
||||
ui->newthreadButton->setText(tr("New thread"));
|
||||
|
||||
connect(ui->threadTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(changedThread()));
|
||||
connect(ui->threadTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(clickedThread(QTreeWidgetItem*,int)));
|
||||
connect(ui->viewBox, SIGNAL(currentIndexChanged(int)), this, SLOT(changedViewBox()));
|
||||
@ -228,6 +231,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
|
||||
/* Set own item delegate */
|
||||
RSElidedItemDelegate *itemDelegate = new RSElidedItemDelegate(this);
|
||||
itemDelegate->setSpacing(QSize(0, 2));
|
||||
itemDelegate->setOnlyPlainText(true);
|
||||
ui->threadTreeWidget->setItemDelegate(itemDelegate);
|
||||
|
||||
/* Set header resize modes and initial section sizes */
|
||||
|
@ -84,6 +84,9 @@
|
||||
<property name="toolTip">
|
||||
<string>Start new Thread for Selected Forum</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New Thread</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/mail_new.png</normaloff>:/images/mail_new.png</iconset>
|
||||
@ -94,6 +97,9 @@
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -306,8 +312,8 @@
|
||||
<widget class="QToolButton" name="newmessageButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
@ -316,10 +322,16 @@
|
||||
<property name="toolTip">
|
||||
<string>Reply Message</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reply</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/mail_reply.png</normaloff>:/images/mail_reply.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -358,7 +370,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<item row="0" column="9">
|
||||
<widget class="Line" name="lineRight">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -471,7 +483,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="9">
|
||||
<item row="0" column="8">
|
||||
<widget class="QComboBox" name="versions_CB"/>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
|
@ -301,8 +301,15 @@ void AppearancePage::load()
|
||||
whileBlocking(ui.checkBoxDisableSysTrayToolTip)->setChecked(Settings->valueFromGroup("StatusBar", "DisableSysTrayToolTip", QVariant(false)).toBool());
|
||||
whileBlocking(ui.checkBoxShowStatusStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowStatus", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowPeerStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowPeer", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowNATStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowNAT", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowDHTStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowDHT", QVariant(true)).toBool());
|
||||
if(MainWindow::hiddenmode) {
|
||||
whileBlocking(ui.checkBoxShowNATStatus)-> setChecked(0);
|
||||
whileBlocking(ui.checkBoxShowDHTStatus)-> setChecked(0);
|
||||
ui.checkBoxShowNATStatus->setVisible(false);
|
||||
ui.checkBoxShowDHTStatus->setVisible(false);
|
||||
} else {
|
||||
whileBlocking(ui.checkBoxShowNATStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowNAT", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowDHTStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowDHT", QVariant(true)).toBool());
|
||||
}
|
||||
whileBlocking(ui.checkBoxShowHashingStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowHashing", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowDiscStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowDisc", QVariant(true)).toBool());
|
||||
whileBlocking(ui.checkBoxShowRateStatus)-> setChecked(Settings->valueFromGroup("StatusBar", "ShowRate", QVariant(true)).toBool());
|
||||
|
@ -152,7 +152,6 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) );
|
||||
connect( ui.cleanKnownIPs_PB, SIGNAL( clicked( ) ), this, SLOT( clearKnownAddressList() ) );
|
||||
connect( ui.testIncoming_PB, SIGNAL( clicked( ) ), this, SLOT( saveAndTestInProxy() ) );
|
||||
connect( ui.showDiscStatusBar,SIGNAL(toggled(bool)),this,SLOT(updateShowDiscStatusBar())) ;
|
||||
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ServerPage::ServerPage() called";
|
||||
@ -160,7 +159,6 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
#endif
|
||||
|
||||
connect(ui.netModeComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses()));
|
||||
connect(ui.discComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses()));
|
||||
connect(ui.localAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses()));
|
||||
connect(ui.extAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses()));
|
||||
connect(ui.dynDNS, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses()));
|
||||
@ -277,8 +275,6 @@ void ServerPage::toggleTunnelConnection(bool b)
|
||||
//rsPeers->allowTunnelConnection(b) ;
|
||||
}
|
||||
|
||||
void ServerPage::updateShowDiscStatusBar() { Settings->setStatusBarFlag(STATUSBAR_DISC, ui.showDiscStatusBar->isChecked()); }
|
||||
|
||||
/** Loads the settings for this page */
|
||||
void ServerPage::load()
|
||||
{
|
||||
@ -303,7 +299,8 @@ void ServerPage::load()
|
||||
if (mIsHiddenNode)
|
||||
{
|
||||
mHiddenType = detail.hiddenType;
|
||||
ui.tabWidget->setTabEnabled(1,false) ;
|
||||
ui.tabWidget->setTabEnabled(1,false) ; // ip filter
|
||||
ui.tabWidget->setTabEnabled(3,false) ; // relay
|
||||
loadHiddenNode();
|
||||
return;
|
||||
}
|
||||
@ -380,7 +377,6 @@ void ServerPage::load()
|
||||
/* set DynDNS */
|
||||
whileBlocking(ui.dynDNS) -> setText(QString::fromStdString(detail.dyndns));
|
||||
|
||||
whileBlocking(ui.showDiscStatusBar)->setChecked(Settings->getStatusBarFlags() & STATUSBAR_DISC);
|
||||
|
||||
whileBlocking(ui.ipAddressList)->clear();
|
||||
for(std::list<std::string>::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it)
|
||||
@ -1004,10 +1000,24 @@ void ServerPage::loadHiddenNode()
|
||||
ui.iconlabel_upnp->hide();
|
||||
ui.label_nat->hide();
|
||||
|
||||
ui.label_warningBandwidth->hide();
|
||||
ui.iconlabel_netLimited->hide();
|
||||
ui.textlabel_netLimited->hide();
|
||||
ui.iconlabel_ext->hide();
|
||||
ui.textlabel_ext->hide();
|
||||
ui.extPortLabel->hide();
|
||||
|
||||
ui.ipAddressLabel->hide();
|
||||
ui.cleanKnownIPs_PB->hide();
|
||||
|
||||
ui.ipAddressList->hide();
|
||||
ui.allowIpDeterminationCB->hide();
|
||||
ui.IPServersLV->hide();
|
||||
|
||||
ui.textlabel_hiddenMode->show();
|
||||
ui.iconlabel_hiddenMode->show() ;
|
||||
ui.iconlabel_hiddenMode->setPixmap(QPixmap(":/images/ledon1.png"));
|
||||
|
||||
|
||||
// CHANGE OPTIONS ON
|
||||
whileBlocking(ui.discComboBox)->removeItem(3);
|
||||
whileBlocking(ui.discComboBox)->removeItem(2);
|
||||
@ -1048,9 +1058,6 @@ void ServerPage::loadHiddenNode()
|
||||
|
||||
whileBlocking(ui.extAddress)->setText(tr("Hidden - See Config"));
|
||||
|
||||
whileBlocking(ui.showDiscStatusBar)->setChecked(Settings->getStatusBarFlags() & STATUSBAR_DISC);
|
||||
ui.showDiscStatusBar->hide() ; // hidden because not functional at the moment.
|
||||
|
||||
//ui._turtle_enabled_CB->setChecked(rsTurtle->enabled()) ;
|
||||
|
||||
// show what we have in ipAddresses. (should be nothing!)
|
||||
|
@ -87,7 +87,6 @@ private slots:
|
||||
// server
|
||||
void saveAddresses();
|
||||
void saveRates();
|
||||
void updateShowDiscStatusBar() ;
|
||||
void toggleUPnP();
|
||||
void toggleIpDetermination(bool) ;
|
||||
void toggleTunnelConnection(bool) ;
|
||||
|
@ -482,13 +482,6 @@ These values don't take into account the Relays.</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="showDiscStatusBar">
|
||||
<property name="text">
|
||||
<string>Show Discovery information in statusbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="allowIpDeterminationCB">
|
||||
<property name="toolTip">
|
||||
<string>If you uncheck this, RetroShare can only determine your IP
|
||||
@ -504,7 +497,7 @@ behind a firewall or a VPN.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QListWidget" name="IPServersLV">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
@ -517,7 +510,7 @@ behind a firewall or a VPN.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="5" column="0">
|
||||
<spacer name="tabNetConfVSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -531,7 +524,6 @@ behind a firewall or a VPN.</string>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>showDiscStatusBar</zorder>
|
||||
<zorder>allowIpDeterminationCB</zorder>
|
||||
<zorder>IPServersLV</zorder>
|
||||
<zorder>ipAddressList</zorder>
|
||||
@ -831,7 +823,7 @@ behind a firewall or a VPN.</string>
|
||||
<item>
|
||||
<widget class="QLabel" name="hiddenpage_outHeader">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Outgoing Connctions</p><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html></string>
|
||||
<string><html><head/><body><p>Configure your Tor and I2P SOCKS proxy here. <br/>If you prefer to use BOB to automatically manage I2P check the other tab.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1475,7 +1467,7 @@ You can connect to Hidden Nodes, even if you are running a standard Node, so why
|
||||
<item>
|
||||
<widget class="QLabel" name="hiddenpage_inHeader">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Incoming Connection</p><p>Setup your hidden address (and port if needed)</p></body></html></string>
|
||||
<string><html><head/><body><p>Setup your hidden address (and port if needed)</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2097,7 +2089,6 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
||||
<tabstop>extAddress</tabstop>
|
||||
<tabstop>extPort</tabstop>
|
||||
<tabstop>dynDNS</tabstop>
|
||||
<tabstop>showDiscStatusBar</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
|
@ -95,10 +95,11 @@ StatisticsWindow::StatisticsWindow(QWidget *parent) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
Settings->loadWidgetInformation(this);
|
||||
|
||||
initStackedPage();
|
||||
connect(ui->stackPages, SIGNAL(currentChanged(int)), this, SLOT(setNewPage(int)));
|
||||
ui->stackPages->setCurrentIndex(0);
|
||||
|
||||
int toolSize = Settings->getToolButtonSize();
|
||||
ui->toolBar->setToolButtonStyle(Settings->getToolButtonStyle());
|
||||
ui->toolBar->setIconSize(QSize(toolSize,toolSize));
|
||||
@ -110,6 +111,11 @@ StatisticsWindow::~StatisticsWindow()
|
||||
mInstance = NULL;
|
||||
}
|
||||
|
||||
void StatisticsWindow::closeEvent (QCloseEvent * /*event*/)
|
||||
{
|
||||
Settings->saveWidgetInformation(this);
|
||||
}
|
||||
|
||||
void StatisticsWindow::changeEvent(QEvent *e)
|
||||
{
|
||||
QMainWindow::changeEvent(e);
|
||||
@ -147,9 +153,19 @@ void StatisticsWindow::initStackedPage()
|
||||
ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp));
|
||||
|
||||
ui->stackPages->add(dhtw = new DhtWindow(ui->stackPages),
|
||||
bool showdht = true;
|
||||
RsPeerDetails detail;
|
||||
if (rsPeers->getPeerDetails(rsPeers->getOwnId(), detail))
|
||||
{
|
||||
if(detail.netMode == RS_NETMODE_HIDDEN)
|
||||
showdht = false;
|
||||
}
|
||||
if(showdht)
|
||||
{
|
||||
ui->stackPages->add(dhtw = new DhtWindow(ui->stackPages),
|
||||
action = createPageAction(QIcon(IMAGE_DHT), tr("DHT"), grp));
|
||||
|
||||
}
|
||||
|
||||
/*std::cerr << "Looking for interfaces in existing plugins:" << std::endl;
|
||||
for(int i = 0;i<rsPlugins->nbPlugins();++i)
|
||||
{
|
||||
|
@ -65,7 +65,8 @@ public slots:
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
void closeEvent (QCloseEvent * event);
|
||||
|
||||
private:
|
||||
void initStackedPage();
|
||||
|
||||
|
@ -476,7 +476,6 @@ HEADERS += rshare.h \
|
||||
gui/common/ElidedLabel.h \
|
||||
gui/common/vmessagebox.h \
|
||||
gui/common/RsUrlHandler.h \
|
||||
gui/common/RsCollectionFile.h \
|
||||
gui/common/RsCollectionDialog.h \
|
||||
gui/common/rwindow.h \
|
||||
gui/common/html.h \
|
||||
@ -568,7 +567,7 @@ HEADERS += rshare.h \
|
||||
util/imageutil.h \
|
||||
gui/NetworkDialog/pgpid_item_model.h \
|
||||
gui/NetworkDialog/pgpid_item_proxy.h
|
||||
|
||||
gui/common/RsCollection.h
|
||||
# gui/ForumsDialog.h \
|
||||
# gui/forums/ForumDetails.h \
|
||||
# gui/forums/EditForumDetails.h \
|
||||
@ -793,7 +792,6 @@ SOURCES += main.cpp \
|
||||
gui/common/RSGraphWidget.cpp \
|
||||
gui/common/ElidedLabel.cpp \
|
||||
gui/common/vmessagebox.cpp \
|
||||
gui/common/RsCollectionFile.cpp \
|
||||
gui/common/RsCollectionDialog.cpp \
|
||||
gui/common/RsUrlHandler.cpp \
|
||||
gui/common/rwindow.cpp \
|
||||
@ -930,7 +928,7 @@ SOURCES += main.cpp \
|
||||
util/imageutil.cpp \
|
||||
gui/NetworkDialog/pgpid_item_model.cpp \
|
||||
gui/NetworkDialog/pgpid_item_proxy.cpp
|
||||
|
||||
gui/common/RsCollection.cpp
|
||||
# gui/ForumsDialog.cpp \
|
||||
# gui/forums/ForumDetails.cpp \
|
||||
# gui/forums/EditForumDetails.cpp \
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "HandleRichText.h"
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "util/ObjectPainter.h"
|
||||
#include "util/imageutil.h"
|
||||
#include "util/rsscopetimer.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -227,6 +229,7 @@ bool RsHtml::canReplaceAnchor(QDomDocument &/*doc*/, QDomElement &/*element*/, c
|
||||
switch (link.type()) {
|
||||
case RetroShareLink::TYPE_UNKNOWN:
|
||||
case RetroShareLink::TYPE_FILE:
|
||||
case RetroShareLink::TYPE_FILE_TREE:
|
||||
case RetroShareLink::TYPE_PERSON:
|
||||
case RetroShareLink::TYPE_FORUM:
|
||||
case RetroShareLink::TYPE_CHANNEL:
|
||||
@ -257,6 +260,7 @@ void RsHtml::anchorStylesheetForImg(QDomDocument &/*doc*/, QDomElement &/*elemen
|
||||
switch (link.type()) {
|
||||
case RetroShareLink::TYPE_UNKNOWN:
|
||||
case RetroShareLink::TYPE_FILE:
|
||||
case RetroShareLink::TYPE_FILE_TREE:
|
||||
case RetroShareLink::TYPE_PERSON:
|
||||
case RetroShareLink::TYPE_FORUM:
|
||||
case RetroShareLink::TYPE_CHANNEL:
|
||||
@ -1105,7 +1109,7 @@ QString RsHtml::toHtml(QString text, bool realHtml)
|
||||
}
|
||||
|
||||
/** Loads image and converts image to embedded image HTML fragment **/
|
||||
bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels)
|
||||
bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels, const int maxBytes)
|
||||
{
|
||||
QImage image;
|
||||
|
||||
@ -1113,54 +1117,15 @@ bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage,
|
||||
fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", fileName.toLatin1().constData());
|
||||
return false;
|
||||
}
|
||||
return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels);
|
||||
return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels, maxBytes);
|
||||
}
|
||||
|
||||
/** Converts image to embedded image HTML fragment **/
|
||||
bool RsHtml::makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels)
|
||||
bool RsHtml::makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes)
|
||||
{
|
||||
QByteArray bytearray;
|
||||
QBuffer buffer(&bytearray);
|
||||
QImage resizedImage;
|
||||
const QImage *image = &originalImage;
|
||||
|
||||
if (maxPixels > 0) {
|
||||
QSize imgSize = originalImage.size();
|
||||
if ((imgSize.height() * imgSize.width()) > maxPixels) {
|
||||
// image is too large - resize keeping aspect ratio
|
||||
QSize newSize;
|
||||
newSize.setWidth(int(qSqrt((maxPixels * imgSize.width()) / imgSize.height())));
|
||||
newSize.setHeight(int((imgSize.height() * newSize.width()) / imgSize.width()));
|
||||
|
||||
// ask user
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(QString(QApplication::translate("RsHtml", "Image is oversized for transmission.\nReducing image to %1x%2 pixels?")).arg(newSize.width()).arg(newSize.height()));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
if (msgBox.exec() != QMessageBox::Ok) {
|
||||
return false;
|
||||
}
|
||||
resizedImage = originalImage.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
image = &resizedImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer.open(QIODevice::WriteOnly)) {
|
||||
if (image->save(&buffer, "PNG")) {
|
||||
QByteArray encodedByteArray = bytearray.toBase64();
|
||||
|
||||
embeddedImage = "<img src=\"data:image/png;base64,";
|
||||
embeddedImage.append(encodedByteArray);
|
||||
embeddedImage.append("\">");
|
||||
} else {
|
||||
//fprintf (stderr, "RsHtml::makeEmbeddedImage() - image can't be saved to buffer\n");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "RsHtml::makeEmbeddedImage() - buffer can't be opened\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
RsScopeTimer s("Embed image");
|
||||
QImage opt;
|
||||
return ImageUtil::optimizeSize(embeddedImage, originalImage, opt, maxPixels, maxBytes);
|
||||
}
|
||||
|
||||
QString RsHtml::plainText(const QString &text)
|
||||
|
@ -69,8 +69,8 @@ public:
|
||||
static void optimizeHtml(QString &text, unsigned int flag = 0, const QColor &backgroundColor = Qt::white, qreal desiredContrast = 1.0, int desiredMinimumFontSize = 10);
|
||||
static QString toHtml(QString text, bool realHtml = true);
|
||||
|
||||
static bool makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels);
|
||||
static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels);
|
||||
static bool makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels, const int maxBytes = -1);
|
||||
static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes = -1);
|
||||
|
||||
static QString plainText(const QString &text);
|
||||
static QString plainText(const std::string &text);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "imageutil.h"
|
||||
#include "util/misc.h"
|
||||
#include "util/rsscopetimer.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
@ -8,6 +9,11 @@
|
||||
#include <QString>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocumentFragment>
|
||||
#include <QBuffer>
|
||||
#include <QtGlobal>
|
||||
#include <QSet>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
ImageUtil::ImageUtil() {}
|
||||
|
||||
@ -42,3 +48,211 @@ void ImageUtil::extractImage(QWidget *window, QTextCursor cursor)
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &optimized, int maxPixels, int maxBytes)
|
||||
{
|
||||
//nothing to do if it fits into the limits
|
||||
optimized = original;
|
||||
if ((maxPixels <= 0) || (optimized.width()*optimized.height() <= maxPixels)) {
|
||||
if(checkSize(html, optimized, maxBytes) <= maxBytes) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QRgb> ct;
|
||||
quantization(original, ct);
|
||||
|
||||
//Downscale the image to fit into maxPixels
|
||||
double whratio = (qreal)original.width() / (qreal)original.height();
|
||||
int maxwidth;
|
||||
if(maxPixels > 0)
|
||||
maxwidth = (int)sqrt((double)(maxPixels) * whratio);
|
||||
else
|
||||
maxwidth = original.width();
|
||||
|
||||
int minwidth = (int)sqrt(100.0 * whratio);
|
||||
|
||||
//if maxBytes not defined, do not reduce color space, just downscale
|
||||
if(maxBytes <= 0) {
|
||||
checkSize(html, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation), maxBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Use binary search to find a suitable image size + linear regression to guess the file size
|
||||
double maxsize = (double)checkSize(html, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes);
|
||||
if(maxsize <= maxBytes) return true; //success
|
||||
double minsize = (double)checkSize(html, optimized = original.scaledToWidth(minwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes);
|
||||
if(minsize > maxBytes) return false; //impossible
|
||||
|
||||
// std::cout << "maxS: " << maxsize << " minS: " << minsize << std::endl;
|
||||
// std::cout << "maxW: " << maxwidth << " minW: " << minwidth << std::endl;
|
||||
int region = 500;
|
||||
bool success = false;
|
||||
do {
|
||||
double m = (maxsize - minsize) / ((double)maxwidth * (double)maxwidth / whratio - (double)minwidth * (double)minwidth / whratio);
|
||||
double b = maxsize - m * ((double)maxwidth * (double)maxwidth / whratio);
|
||||
double a = ((double)(maxBytes - region/2) - b) / m; //maxBytes - region/2 target the center of the accepted region
|
||||
int nextwidth = (int)sqrt(a * whratio);
|
||||
double nextsize = (double)checkSize(html, optimized = original.scaledToWidth(nextwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes);
|
||||
if(nextsize <= maxBytes) {
|
||||
minsize = nextsize;
|
||||
minwidth = nextwidth;
|
||||
if(nextsize >= (maxBytes - region)) //the file size is close anough to the limit
|
||||
success = true;
|
||||
} else {
|
||||
maxsize = nextsize;
|
||||
maxwidth = nextwidth;
|
||||
}
|
||||
// std::cout << "maxS: " << maxsize << " minS: " << minsize << std::endl;
|
||||
// std::cout << "maxW: " << maxwidth << " minW: " << minwidth << std::endl;
|
||||
} while(!success);
|
||||
return true;
|
||||
//html = html.arg(original.width());
|
||||
//std::cout << html.toStdString() << std::endl;
|
||||
}
|
||||
|
||||
int ImageUtil::checkSize(QString &embeddedImage, const QImage &img, int maxBytes)
|
||||
{
|
||||
RsScopeTimer st("Check size");
|
||||
|
||||
QByteArray bytearray;
|
||||
QBuffer buffer(&bytearray);
|
||||
int size = 0;
|
||||
|
||||
//std::cout << QString("Trying image: format PNG, size %1x%2, colors %3\n").arg(img.width()).arg(img.height()).arg(img.colorCount()).toStdString();
|
||||
if (buffer.open(QIODevice::WriteOnly)) {
|
||||
if (img.save(&buffer, "PNG", 0)) {
|
||||
size = bytearray.length() * 4/3;
|
||||
if((maxBytes > 0) && (size > maxBytes)) // *4/3 for base64
|
||||
{
|
||||
//std::cout << QString("\tToo large, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString();
|
||||
}else{
|
||||
//std::cout << QString("\tOK, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString();
|
||||
QByteArray encodedByteArray = bytearray.toBase64();
|
||||
//embeddedImage = "<img width=\"%1\" src=\"data:image/png;base64,";
|
||||
embeddedImage = "<img src=\"data:image/png;base64,";
|
||||
embeddedImage.append(encodedByteArray);
|
||||
embeddedImage.append("\">");
|
||||
}
|
||||
} else {
|
||||
std::cerr << "ImageUtil: image can't be saved to buffer" << std::endl;
|
||||
}
|
||||
buffer.close();
|
||||
bytearray.clear();
|
||||
} else {
|
||||
std::cerr << "ImageUtil: buffer can't be opened" << std::endl;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool redLessThan(const QRgb &c1, const QRgb &c2)
|
||||
{
|
||||
return qRed(c1) < qRed(c2);
|
||||
}
|
||||
|
||||
bool greenLessThan(const QRgb &c1, const QRgb &c2)
|
||||
{
|
||||
return qGreen(c1) < qGreen(c2);
|
||||
}
|
||||
|
||||
bool blueLessThan(const QRgb &c1, const QRgb &c2)
|
||||
{
|
||||
return qBlue(c1) < qBlue(c2);
|
||||
}
|
||||
|
||||
//median cut algoritmh
|
||||
void ImageUtil::quantization(const QImage &img, QVector<QRgb> &palette)
|
||||
{
|
||||
int bits = 4; // bits/pixel
|
||||
int samplesize = 100000; //only take this many color samples
|
||||
|
||||
RsScopeTimer st("Quantization");
|
||||
QSet<QRgb> colors;
|
||||
|
||||
//collect color information
|
||||
int imgsize = img.width()*img.height();
|
||||
int width = img.width();
|
||||
samplesize = qMin(samplesize, imgsize);
|
||||
double sampledist = (double)imgsize / (double)samplesize;
|
||||
for (double i = 0; i < imgsize; i += sampledist) {
|
||||
QRgb pixel = img.pixel((int)i % width, (int)i / width);
|
||||
colors.insert(pixel);
|
||||
}
|
||||
|
||||
QList<QRgb> colorlist = colors.toList();
|
||||
//don't do the algoritmh if we have less than 16 different colors
|
||||
if(colorlist.size() <= (1 << bits)) {
|
||||
for(int i = 0; i < colors.count(); ++i)
|
||||
palette.append(colorlist[i]);
|
||||
} else {
|
||||
quantization(colorlist.begin(), colorlist.end(), bits, palette);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageUtil::quantization(QList<QRgb>::iterator begin, QList<QRgb>::iterator end, int depth, QVector<QRgb> &palette)
|
||||
{
|
||||
//the buckets are ready
|
||||
if(depth == 0) {
|
||||
avgbucket(begin, end, palette);
|
||||
return;
|
||||
}
|
||||
|
||||
//nothing to do
|
||||
int count = end - begin;
|
||||
if(count == 1) {
|
||||
palette.append(*begin);
|
||||
return;
|
||||
}
|
||||
|
||||
//widest color channel
|
||||
int rl = 255;
|
||||
int gl = 255;
|
||||
int bl = 255;
|
||||
int rh = 0;
|
||||
int gh = 0;
|
||||
int bh = 0;
|
||||
for(QList<QRgb>::iterator it = begin; it < end; ++it) {
|
||||
rl = qMin(rl, qRed(*it));
|
||||
gl = qMin(gl, qGreen(*it));
|
||||
bl = qMin(bl, qBlue(*it));
|
||||
rh = qMax(rh, qRed(*it));
|
||||
gh = qMax(gh, qGreen(*it));
|
||||
bh = qMax(bh, qBlue(*it));
|
||||
}
|
||||
int red = rh - rl;
|
||||
int green = gh - gl;
|
||||
int blue = bh - bl;
|
||||
|
||||
//order by the widest channel
|
||||
if(red > green)
|
||||
if(red > blue)
|
||||
qSort(begin, end, redLessThan);
|
||||
else
|
||||
qSort(begin, end, blueLessThan);
|
||||
else
|
||||
if(green > blue)
|
||||
qSort(begin, end, greenLessThan);
|
||||
else
|
||||
qSort(begin, end, blueLessThan);
|
||||
|
||||
//split into two buckets
|
||||
QList<QRgb>::iterator split = begin + count / 2;
|
||||
quantization(begin, split, depth - 1, palette);
|
||||
quantization(split, end, depth - 1, palette);
|
||||
}
|
||||
|
||||
void ImageUtil::avgbucket(QList<QRgb>::iterator begin, QList<QRgb>::iterator end, QVector<QRgb> &palette)
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int count = end - begin;
|
||||
|
||||
for(QList<QRgb>::iterator it = begin; it < end; ++it) {
|
||||
red += qRed(*it);
|
||||
green += qGreen(*it);
|
||||
blue += qBlue(*it);
|
||||
}
|
||||
|
||||
QRgb color = qRgb(red/count, green/count, blue/count);
|
||||
palette.append(color);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QTextCursor>
|
||||
#include <QWidget>
|
||||
#include <qiterator.h>
|
||||
|
||||
class ImageUtil
|
||||
{
|
||||
@ -10,6 +11,13 @@ public:
|
||||
ImageUtil();
|
||||
|
||||
static void extractImage(QWidget *window, QTextCursor cursor);
|
||||
static bool optimizeSize(QString &html, const QImage& original, QImage &optimized, int maxPixels = -1, int maxBytes = -1);
|
||||
|
||||
private:
|
||||
static int checkSize(QString& embeddedImage, const QImage& img, int maxBytes = -1);
|
||||
static void quantization(const QImage& img, QVector<QRgb>& palette);
|
||||
static void quantization(QList<QRgb>::iterator begin, QList<QRgb>::iterator end, int depth, QVector<QRgb>& palette);
|
||||
static void avgbucket(QList<QRgb>::iterator begin, QList<QRgb>::iterator end, QVector<QRgb>& palette);
|
||||
};
|
||||
|
||||
#endif // IMAGEUTIL_H
|
||||
|
@ -28,7 +28,7 @@ Item
|
||||
{
|
||||
id: chatView
|
||||
property string chatId
|
||||
property var gxsInfo: ""
|
||||
property var gxsInfo: ({})
|
||||
property int token: 0
|
||||
|
||||
property string objectName:"chatView"
|
||||
@ -64,7 +64,7 @@ Item
|
||||
function changeState ()
|
||||
{
|
||||
toolBar.state = "CHATVIEW"
|
||||
gxsInfo= ChatCache.lastMessageCache.getGxsFromChatId(chatView.chatId)
|
||||
gxsInfo = ChatCache.lastMessageCache.getGxsFromChatId(chatView.chatId)
|
||||
toolBar.gxsSource = gxsInfo.gxs
|
||||
toolBar.titleText = gxsInfo.name
|
||||
}
|
||||
@ -100,7 +100,7 @@ Item
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: parent.height / 2
|
||||
anchors.bottomMargin: categorySelectorHeight
|
||||
anchors.bottomMargin: if(!androidMode) categorySelectorHeight
|
||||
|
||||
property int categorySelectorHeight: 50
|
||||
|
||||
@ -114,6 +114,7 @@ Item
|
||||
name: "EMOJI_HIDDEN"
|
||||
PropertyChanges { target: emojiPicker; anchors.topMargin: parent.height }
|
||||
PropertyChanges { target: emojiPicker; anchors.bottomMargin: -1 }
|
||||
PropertyChanges { target: emojiPicker; height: 0 }
|
||||
},
|
||||
State {
|
||||
name: "EMOJI_SHOWN"
|
||||
@ -132,7 +133,7 @@ Item
|
||||
id: inferiorPanel
|
||||
height: ( msgComposer.height > styles.height)? msgComposer.height: styles.height
|
||||
width: parent.width
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottom: emojiPicker.androidMode ? emojiPicker.top : parent.bottom
|
||||
|
||||
Rectangle
|
||||
{
|
||||
|
@ -50,7 +50,14 @@ Item
|
||||
console.log("GxsIntentityDelegate onclicked:", model.name,
|
||||
model.gxs_id)
|
||||
contactsView.searching = false
|
||||
if(model.own) contactsView.own_gxs_id = model.gxs_id
|
||||
if(model.own)
|
||||
{
|
||||
contactsView.own_gxs_id = model.gxs_id
|
||||
stackView.push(
|
||||
"qrc:/ContactDetails.qml",
|
||||
{md: ChatCache.contactsCache.getContactFromGxsId(model.gxs_id)})
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
startDistantChat()
|
||||
|
@ -28,6 +28,13 @@ QtObject
|
||||
property var tokens: ({})
|
||||
function registerToken(token, callback)
|
||||
{
|
||||
if(!maybeToken(token))
|
||||
{
|
||||
console.error("TokensManager attempt to register a non int token")
|
||||
console.trace()
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(tokens[token]))
|
||||
{
|
||||
if(QT_DEBUG)
|
||||
@ -72,6 +79,7 @@ QtObject
|
||||
delete tokens[token]
|
||||
}
|
||||
function isTokenValid(token) { return Array.isArray(tokens[token]) }
|
||||
function maybeToken(value) { return Number(value) === parseInt(value) }
|
||||
|
||||
property alias refreshInterval: refreshTokensTimer.interval
|
||||
|
||||
@ -81,16 +89,22 @@ QtObject
|
||||
|
||||
onResponseReceived:
|
||||
{
|
||||
/* TODO: This is vital enough and if some fails appens can create
|
||||
* difficult to debug unexpected behaviours in any place of the app.
|
||||
* We should do some more checking on the data received here
|
||||
*/
|
||||
var jsonData = JSON.parse(msg).data
|
||||
// console.log("refreshTokensApi got expired tokens:", msg)
|
||||
var arrayLength = jsonData.length
|
||||
for (var i = 0; i < arrayLength; i++)
|
||||
{
|
||||
for (var i = 0; i < arrayLength; ++i)
|
||||
tokensManager.tokenExpire(jsonData[i])
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
/* Disable debugging only for this instance of LibresapiLocalClient
|
||||
* as it is particularly noisy and repetitive, and not useful in
|
||||
* most of the cases */
|
||||
if(QT_DEBUG) debug = false
|
||||
|
||||
openConnection(apiSocketPath)
|
||||
@ -99,8 +113,13 @@ QtObject
|
||||
|
||||
function refreshTokens()
|
||||
{
|
||||
request("/statetokenservice/*",
|
||||
'['+Object.keys(tokensManager.tokens)+']')
|
||||
var tokensArr = Object.keys(tokensManager.tokens)
|
||||
|
||||
// Filter to avoid "undefined" being sent toghether with tokens
|
||||
var tokensStr = '['+ tokensArr.filter(maybeToken) +']'
|
||||
|
||||
// console.log("refreshTokensApi checking tokens:", tokensStr)
|
||||
request("/statetokenservice/*", tokensStr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,4 +6,4 @@
|
||||
androidBuildToolsVersion=24.0.1
|
||||
androidCompileSdkVersion=23
|
||||
buildDir=.build
|
||||
qt5AndroidDir=/opt/Qt5.8.0/5.8/android_armv7/src/android/java
|
||||
qt5AndroidDir=/opt/Qt/5.9.2/android_armv7/src/android/java
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
|
||||
#include "qpainter.h"
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <QtAndroid>
|
||||
@ -41,14 +43,44 @@ public slots:
|
||||
QString localPath = url.toLocalFile();
|
||||
|
||||
qDebug() << "imageToBase64() local path:" << localPath ;
|
||||
|
||||
// Read the image
|
||||
QImageReader reader;
|
||||
reader.setFileName(localPath);
|
||||
QImage image = reader.read();
|
||||
QImage image= getImage (localPath);
|
||||
|
||||
image = image.scaled(96,96,Qt::KeepAspectRatio,Qt::SmoothTransformation);
|
||||
|
||||
qDebug() << "imageToBase64() encoding" ;
|
||||
|
||||
return imageToB64(image);
|
||||
}
|
||||
|
||||
static QString b64AvatarGen (QVariantList onloads, int size)
|
||||
{
|
||||
qDebug() << "b64AvatarGen(): Generating face Avatar from";
|
||||
|
||||
QImage result(size, size, QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter painter(&result);
|
||||
|
||||
|
||||
int counter = 0;
|
||||
for (QVariantList::iterator j = onloads.begin(); j != onloads.end(); j++)
|
||||
{
|
||||
QImage image = getImage (":/"+(*j).toString());
|
||||
painter.drawImage(0, 0, image); // xi, yi is the position for imagei
|
||||
counter++;
|
||||
}
|
||||
painter.end();
|
||||
|
||||
return imageToB64(result);
|
||||
}
|
||||
|
||||
static QImage getImage (QString const& path)
|
||||
{
|
||||
QImageReader reader;
|
||||
reader.setFileName(path);
|
||||
return reader.read();
|
||||
}
|
||||
|
||||
static QString imageToB64 (QImage image)
|
||||
{
|
||||
// Transform image into PNG format
|
||||
QByteArray ba;
|
||||
QBuffer buffer( &ba );
|
||||
@ -56,11 +88,8 @@ public slots:
|
||||
image.save( &buffer, "png" );
|
||||
|
||||
// Get Based 64 image string
|
||||
QString encoded = QString(ba.toBase64());
|
||||
|
||||
qDebug() << "imageToBase64() encoded" ;
|
||||
|
||||
return encoded;
|
||||
|
||||
return QString(ba.toBase64());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
@ -4,64 +4,22 @@ import "../" // Needed by ChatCache (where stores generated faces)
|
||||
|
||||
Item
|
||||
{
|
||||
|
||||
id: faces
|
||||
|
||||
property string hash
|
||||
property var facesCache: ChatCache.facesCache
|
||||
|
||||
|
||||
Image
|
||||
{
|
||||
id: imageAvatar
|
||||
width: height
|
||||
height: iconSize
|
||||
visible: true
|
||||
}
|
||||
|
||||
Canvas
|
||||
{
|
||||
id: canvasAvatar
|
||||
width: height
|
||||
height: canvasSizes
|
||||
visible: false
|
||||
|
||||
renderStrategy: Canvas.Threaded;
|
||||
renderTarget: Canvas.Image;
|
||||
|
||||
property var images
|
||||
property var callback
|
||||
|
||||
|
||||
onPaint:
|
||||
{
|
||||
var ctx = getContext("2d");
|
||||
|
||||
if (images)
|
||||
{
|
||||
for (y = 0 ; y< nPieces ; y++)
|
||||
{
|
||||
ctx.drawImage(images[y], 0, 0, iconSize, iconSize )
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onPainted:
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
var data = toDataURL('image/png')
|
||||
callback(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
createFromHex(hash)
|
||||
}
|
||||
Component.onCompleted: createFromHex(hash)
|
||||
|
||||
/* TODO: Is there a reason why we are using var and not proper type for the
|
||||
* following properties? */
|
||||
|
||||
property var facesPath: "/icons/faces/"
|
||||
|
||||
@ -134,11 +92,9 @@ Item
|
||||
{
|
||||
var url = src(gender, i, data[i+1])
|
||||
onloads.push(url)
|
||||
canvasAvatar.loadImage(url)
|
||||
}
|
||||
canvasAvatar.images = onloads
|
||||
canvasAvatar.callback = callback
|
||||
canvasAvatar.requestPaint()
|
||||
var base64Image = androidImagePicker.b64AvatarGen(onloads, canvasSizes)
|
||||
callback("data:image/png;base64,"+base64Image)
|
||||
}
|
||||
|
||||
// Create the identicon
|
||||
@ -146,32 +102,11 @@ Item
|
||||
{
|
||||
var iconId = [dataHex, iconSize];
|
||||
var update = function(data)
|
||||
{
|
||||
// This conditions are for solve a bug on an Lg S3.
|
||||
// On this device the toDataURL() is incompleted.
|
||||
// So for see the complete avatar at least at first execution we'll show the canvas,
|
||||
// instead of the image component.
|
||||
// See issue: https://gitlab.com/angesoc/RetroShare/issues/37
|
||||
if (facesCache.iconCache[iconId])
|
||||
{
|
||||
imageAvatar.source = data
|
||||
imageAvatar.visible = true
|
||||
canvasAvatar.visible = false
|
||||
|
||||
canvasAvatar.height = 0
|
||||
imageAvatar.height = iconSize
|
||||
}
|
||||
else
|
||||
{
|
||||
canvasAvatar.visible = true
|
||||
imageAvatar.visible = false
|
||||
|
||||
canvasAvatar.height = iconSize
|
||||
imageAvatar.height = 0
|
||||
}
|
||||
|
||||
facesCache.iconCache[iconId] = data;
|
||||
}
|
||||
{
|
||||
imageAvatar.source = data
|
||||
imageAvatar.height = iconSize
|
||||
facesCache.iconCache[iconId] = data;
|
||||
}
|
||||
|
||||
if (facesCache.iconCache.hasOwnProperty(iconId))
|
||||
{
|
||||
@ -184,13 +119,13 @@ Item
|
||||
else
|
||||
{
|
||||
var onImageGenerated = function(data)
|
||||
{
|
||||
{
|
||||
|
||||
facesCache.callbackCache[iconId].forEach(function(callback)
|
||||
{
|
||||
callback(data);
|
||||
})
|
||||
}
|
||||
facesCache.callbackCache[iconId].forEach(function(callback)
|
||||
{
|
||||
callback(data);
|
||||
})
|
||||
}
|
||||
|
||||
facesCache.callbackCache[iconId] = [update];
|
||||
if (dataHex)
|
||||
|
@ -1,12 +1,14 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls.Styles 1.2
|
||||
|
||||
Rectangle {
|
||||
Rectangle
|
||||
{
|
||||
id: emojiButton
|
||||
|
||||
property var fontName
|
||||
|
||||
Text {
|
||||
Text
|
||||
{
|
||||
id: emojiText
|
||||
color: "gray"
|
||||
text: qsTr(eCatText)
|
||||
@ -17,17 +19,22 @@ Rectangle {
|
||||
|
||||
|
||||
state: "RELEASED"
|
||||
states: [
|
||||
State {
|
||||
states:
|
||||
[
|
||||
State
|
||||
{
|
||||
name: "PRESSED"
|
||||
PropertyChanges {
|
||||
PropertyChanges
|
||||
{
|
||||
target: emojiText
|
||||
font.pixelSize: emojiButton.width - 10
|
||||
}
|
||||
},
|
||||
State {
|
||||
State
|
||||
{
|
||||
name: "RELEASED"
|
||||
PropertyChanges {
|
||||
PropertyChanges
|
||||
{
|
||||
target: emojiText
|
||||
font.pixelSize: emojiButton.width - 8
|
||||
}
|
||||
@ -35,20 +42,25 @@ Rectangle {
|
||||
]
|
||||
|
||||
|
||||
MouseArea {
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onEntered: {
|
||||
onEntered:
|
||||
{
|
||||
emojiText.color = "black"
|
||||
}
|
||||
onExited: {
|
||||
onExited:
|
||||
{
|
||||
emojiText.color = "gray"
|
||||
}
|
||||
onPressedChanged: {
|
||||
onPressedChanged:
|
||||
{
|
||||
emojiButton.state = emojiButton.state == "PRESSED" ? "RELEASED" : "PRESSED"
|
||||
}
|
||||
onClicked: {
|
||||
onClicked:
|
||||
{
|
||||
Qt.emojiClickedHandler(emojiText.text)
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,37 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls.Styles 1.2
|
||||
|
||||
Rectangle {
|
||||
Rectangle
|
||||
{
|
||||
id: emojiCategoryButton
|
||||
property string categoryName
|
||||
|
||||
property var fontName
|
||||
|
||||
|
||||
function completedHandler() {
|
||||
function completedHandler()
|
||||
{
|
||||
categoryName = eCatName
|
||||
|
||||
//initialize
|
||||
if (parent.currSelEmojiButton === undefined) {
|
||||
if (parent.currSelEmojiButton === undefined)
|
||||
{
|
||||
clickedHandler()
|
||||
}
|
||||
}
|
||||
|
||||
function pressedHandler() {
|
||||
if (state != "SELECTED") {
|
||||
function pressedHandler()
|
||||
{
|
||||
if (state != "SELECTED")
|
||||
{
|
||||
state = state == "PRESSED" ? "RELEASED" : "PRESSED"
|
||||
}
|
||||
}
|
||||
|
||||
function clickedHandler() {
|
||||
if (parent.currSelEmojiButton !== undefined) {
|
||||
function clickedHandler()
|
||||
{
|
||||
if (parent.currSelEmojiButton !== undefined)
|
||||
{
|
||||
parent.currSelEmojiButton.state = "RELEASED"
|
||||
}
|
||||
|
||||
@ -34,7 +41,8 @@ Rectangle {
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
Text
|
||||
{
|
||||
id: emojiText
|
||||
color: "gray"
|
||||
text: qsTr(eCatText)
|
||||
@ -45,31 +53,39 @@ Rectangle {
|
||||
|
||||
|
||||
state: "RELEASED"
|
||||
states: [
|
||||
State {
|
||||
states:
|
||||
[
|
||||
State
|
||||
{
|
||||
name: "PRESSED"
|
||||
PropertyChanges {
|
||||
PropertyChanges
|
||||
{
|
||||
target: emojiText
|
||||
font.pixelSize: emojiCategoryButton.width - 10
|
||||
}
|
||||
},
|
||||
State {
|
||||
State
|
||||
{
|
||||
name: "RELEASED"
|
||||
PropertyChanges {
|
||||
PropertyChanges
|
||||
{
|
||||
target: emojiText
|
||||
font.pixelSize: emojiCategoryButton.width - 8
|
||||
}
|
||||
},
|
||||
State {
|
||||
State
|
||||
{
|
||||
name: "SELECTED"
|
||||
PropertyChanges {
|
||||
PropertyChanges
|
||||
{
|
||||
target: emojiCategoryButton
|
||||
color: "#ADD6FF"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
MouseArea {
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: emojiText.color = "black"
|
||||
|
@ -2,33 +2,41 @@ import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import "emoji.js" as EmojiJSON
|
||||
|
||||
Rectangle {
|
||||
Rectangle
|
||||
{
|
||||
id: emojiPicker
|
||||
property EmojiCategoryButton currSelEmojiButton
|
||||
property variant emojiParsedJson
|
||||
property int buttonWidth: 40
|
||||
property TextArea textArea
|
||||
|
||||
property bool androidMode: Qt.platform.os === "android" // On Desktop appears on top of text field, instead appears in place of virtual keyboard (under text field)
|
||||
|
||||
|
||||
property var rootFontName: theme.emojiFontName
|
||||
|
||||
//displays all Emoji of one categroy by modifying the ListModel of emojiGrid
|
||||
function categoryChangedHandler (newCategoryName){
|
||||
function categoryChangedHandler (newCategoryName)
|
||||
{
|
||||
emojiByCategory.clear()
|
||||
|
||||
for (var i = 0; i < emojiParsedJson.emoji_by_category[newCategoryName].length; i++) {
|
||||
for (var i = 0; i < emojiParsedJson.emoji_by_category[newCategoryName].length; i++)
|
||||
{
|
||||
var elem = emojiParsedJson.emoji_by_category[newCategoryName][i]
|
||||
emojiByCategory.append({eCatName: newCategoryName, eCatText: elem})
|
||||
}
|
||||
}
|
||||
|
||||
//adds the clicked Emoji (and one ' ' if the previous character isn't an Emoji) to textArea
|
||||
function emojiClickedHandler(selectedEmoji) {
|
||||
function emojiClickedHandler(selectedEmoji)
|
||||
{
|
||||
var strAppnd = ""
|
||||
var plainText = textArea.getText(0, textArea.length)
|
||||
|
||||
if (plainText.length > 0) {
|
||||
var lastChar = plainText[plainText.length-1]
|
||||
if ((lastChar !== ' ') && (lastChar.charCodeAt(0) < 255)) {
|
||||
if ((lastChar !== ' ') && (lastChar.charCodeAt(0) < 255))
|
||||
{
|
||||
strAppnd = " "
|
||||
}
|
||||
}
|
||||
@ -38,10 +46,12 @@ Rectangle {
|
||||
}
|
||||
|
||||
//parses JSON, publishes button handlers and inits textArea
|
||||
function completedHandler() {
|
||||
function completedHandler()
|
||||
{
|
||||
// emojiParsedJson = JSON.parse(EmojiJSON.emoji_json)
|
||||
emojiParsedJson = EmojiJSON.emoji_json
|
||||
for (var i = 0; i < emojiParsedJson.emoji_categories.length; i++) {
|
||||
for (var i = 0; i < emojiParsedJson.emoji_categories.length; i++)
|
||||
{
|
||||
var elem = emojiParsedJson.emoji_categories[i]
|
||||
emojiCategoryButtons.append({eCatName: elem.name, eCatText: elem.emoji_unified})
|
||||
}
|
||||
@ -56,29 +66,39 @@ Rectangle {
|
||||
|
||||
//checks if the previous character is an Emoji and adds a ' ' if that's the case
|
||||
//this is necessary, because Emoji use a bigger font-size, and that font-size is kept using without a ' '
|
||||
function keyPressedHandler(event) {
|
||||
function keyPressedHandler(event)
|
||||
{
|
||||
var testStr = textArea.getText(textArea.length-2, textArea.length)
|
||||
var ptrn = new RegExp("[\uD800-\uDBFF][\uDC00-\uDFFF]")
|
||||
if ((event.key !== Qt.Key_Backspace) && (ptrn.test(testStr))) {
|
||||
if ((event.key !== Qt.Key_Backspace) && (ptrn.test(testStr)))
|
||||
{
|
||||
textArea.text += " "
|
||||
textArea.cursorPosition = textArea.length
|
||||
}
|
||||
}
|
||||
|
||||
//all emoji of one category
|
||||
ListModel {
|
||||
ListModel
|
||||
{
|
||||
id: emojiByCategory
|
||||
}
|
||||
|
||||
GridView {
|
||||
GridView
|
||||
{
|
||||
id: emojiGrid
|
||||
width: parent.width
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: buttonWidth
|
||||
cellWidth: buttonWidth; cellHeight: buttonWidth
|
||||
anchors.fill: parent
|
||||
anchors
|
||||
{
|
||||
bottomMargin: if (!androidMode) buttonWidth
|
||||
topMargin: if (androidMode) buttonWidth
|
||||
}
|
||||
|
||||
cellWidth: buttonWidth; cellHeight: buttonWidth
|
||||
|
||||
model: emojiByCategory
|
||||
delegate: EmojiButton {
|
||||
delegate: EmojiButton
|
||||
{
|
||||
width: buttonWidth
|
||||
height: buttonWidth
|
||||
color: emojiPicker.color
|
||||
@ -88,37 +108,52 @@ Rectangle {
|
||||
|
||||
|
||||
//seperator
|
||||
Rectangle {
|
||||
color: emojiPicker.color
|
||||
anchors.bottom: parent.bottom
|
||||
Rectangle
|
||||
{
|
||||
color: "gray"
|
||||
anchors
|
||||
{
|
||||
bottom: if (!androidMode) parent.bottom
|
||||
top: if (androidMode) parent.top
|
||||
bottomMargin: if (!androidMode) buttonWidth
|
||||
topMargin: if (androidMode) buttonWidth
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
height: 1
|
||||
}
|
||||
Rectangle
|
||||
{
|
||||
color: emojiPicker.color
|
||||
width: parent.width
|
||||
height: buttonWidth
|
||||
}
|
||||
Rectangle {
|
||||
color: "black"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: buttonWidth
|
||||
width: parent.width
|
||||
height: 1
|
||||
|
||||
anchors
|
||||
{
|
||||
bottom: if (!androidMode) parent.bottom
|
||||
top: if (androidMode) parent.top
|
||||
}
|
||||
|
||||
//emoji category selector
|
||||
ListView
|
||||
{
|
||||
width: parent.width
|
||||
orientation: ListView.Horizontal
|
||||
anchors.fill: parent
|
||||
|
||||
model: emojiCategoryButtons
|
||||
delegate: EmojiCategoryButton
|
||||
{
|
||||
width: buttonWidth
|
||||
height: buttonWidth
|
||||
color: emojiPicker.color
|
||||
fontName: rootFontName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//emoji category selector
|
||||
ListView {
|
||||
width: parent.width
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: buttonWidth
|
||||
orientation: ListView.Horizontal
|
||||
|
||||
model: emojiCategoryButtons
|
||||
delegate: EmojiCategoryButton {
|
||||
width: buttonWidth
|
||||
height: buttonWidth
|
||||
color: emojiPicker.color
|
||||
fontName: rootFontName
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
ListModel
|
||||
{
|
||||
id: emojiCategoryButtons
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ android-g++ {
|
||||
# message(ANDROID_EXTRA_LIBS: $$ANDROID_EXTRA_LIBS)
|
||||
# message(ANDROID_PLATFORM: $$ANDROID_PLATFORM)
|
||||
# message(ANDROID_PLATFORM_ROOT_PATH: $$ANDROID_PLATFORM_ROOT_PATH)
|
||||
# message(NDK_TOOLCHAIN_PATH: $$NDK_TOOLCHAIN_PATH)
|
||||
# message(NATIVE_LIBS_TOOLCHAIN_PATH: $$NATIVE_LIBS_TOOLCHAIN_PATH)
|
||||
}
|
||||
|
||||
win32 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user